/surosql/wordpress_plugin/surosql/src/Surosql.class.php
PHP | 467 lines | 409 code | 55 blank | 3 comment | 94 complexity | df208cf599c030d1f4aa8d13bc1ff494 MD5 | raw file
Possible License(s): LGPL-3.0, AGPL-1.0, GPL-2.0, LGPL-2.1
- <?php
-
- // version 0.4
-
- class Surosql {
-
- /* table - global alias - (fieldname) - localalias */
-
- public $aliases = array();
- public $class2info = array();
- public $connections = array();
- public $imported_query_functions = array();
- public $imported_osql_functions = array();
-
- function __call($method, $args) {
- return call_user_func_array($this->imported_osql_functions[$method], array_merge(array($this), $args));
- }
-
- static function field_serialization($values, $info, $type = 'serialize') {
- $default_serialize = array('serialize', 'unserialize');
- $type = $type == 'serialize' ? 0 : 1;
- if(!isset($info['serialization'])) {
- return $values;
- }
- foreach($info['serialization'] as $key => $val) {
- $field_name = is_array($val) ? $key : $val;
- if(isset($values[$field_name])) {
- $serialization_func = is_array($val) ? $val : $default_serialize;
- $values[$field_name] = call_user_func($serialization_func[$type], $values[$field_name]);
- }
- }
- return $values;
- }
-
- static function array_flatten($array) {
- if(!is_array($array)) {
- return $array;
- }
- $return_array = array();
- foreach($array as $key => $val) {
- if(is_array($val)) {
- $return_array = array_merge($return_array, self::array_flatten($val));
- } else if(is_int($val)) {
- $return_array[] = $val;
- } else {
- $return_array[$key] = $val;
- }
- }
- return $return_array;
- }
-
- function logand() {
- $args = func_get_args();
- $args = self::array_flatten($args);
- return count($args) === 0 ? '1' : '(' . implode(') AND (', $args) . ')';
- }
-
- function logor() {
- $args = func_get_args();
- $args = self::array_flatten($args);
- return count($args) === 0 ? '0' : '(' . implode(') OR (', $args) . ')';
- }
-
- function glalias2table($glalias) {
- return !isset($this->aliases[$glalias]['table']) ? $glalias : $this->aliases[$glalias]['table'];
- }
-
- function connect($glalias, $connection, $extra = array()) {
- preg_match('/^(.*?)\s*-\s*(.*?)\s*(\(\s*(.*?)\s*\))? *$/', $glalias, $matches);
- list($_, $base, $fieldname) = $matches;
- $basetable = $this->glalias2table($base);
- $fieldglalias = (count($matches) == 5 ? $matches[4] : $fieldname);
- $fieldtable = $this->glalias2table($fieldglalias);
- $connection = str_replace("%$base%", "%$basetable%", $connection);
- $extra = array_merge(array('jointype' => 'INNER'), $extra);
- $this->connections["$base,$fieldname"] = array('sqljoin' => $connection, 'table' => $fieldtable, 'glalias' => $fieldglalias, 'extra' => $extra);
- return $this;
- }
-
- function get_class_info($classname) {
- if(isset($this->class2info[$classname])) {
- return $this->class2info[$classname];
- }
- $refclass = new ReflectionClass($classname);
- $info = $refclass->getStaticPropertyValue('surosql', array());
- if(!is_null($refclass->getConstructor())) {
- $ooinit = array($refclass, 'newInstance');
- } else {
- $ooinit = create_function('$a', "return Surosql::array_to_class(\$a, '$classname');");
- }
- $classvars = array_keys(array_diff_key(get_class_vars($classname), $refclass->getStaticProperties()));
- $info = array_merge(array('connections' => array(), 'table' => $classname, 'class' => $classname, 'ooinit' => $ooinit, 'classvars' => $classvars), $info);
- if(isset($info['alias'])) {
- $this->aliases[$info['alias']] = $info;
- foreach($info['connections'] as $connid => $connsql) {
- $this->connect("{$info['alias']} - $connid", $connsql);
- }
- }
- $this->class2info[$classname] = $info;
- return $info;
- }
-
- function addclass() {
- $func_args = func_get_args();
- foreach(self::array_flatten($func_args) as $classname) {
- $this->get_class_info($classname);
- }
- return $this;
- }
-
- function get_obj_info($obj) {
- $info = $this->get_class_info(get_class($obj));
- return isset($info['columns']) ? $info : array_merge($info, array('columns' => array_keys(get_object_vars($obj))));
- }
-
- static function array_to_class($arr, $classname) {
- $obj = new $classname();
- foreach($arr as $key => $value) {
- $obj->$key = $value;
- }
- return $obj;
- }
-
- function count() {
- $query = new SurosqlQuery($this);
- return $query->count();
- }
-
- function select($args = '%*') {
- $query = new SurosqlQuery($this);
- return $query->select($args);
- }
-
- function selectoo($args = '%*') {
- $query = new SurosqlQuery($this);
- return $query->selectoo($args);
- }
-
- function from($from) {
- return $this->select()->from($from);
- }
-
- function fromoo($from) {
- return $this->selectoo()->from($from);
- }
-
- function __get($from) {
- return $this->selectoo()->from($from);
- }
-
- function update($from = null) {
- $query = new SurosqlQuery($this);
- return $query->update($from);
- }
- }
-
- class SurosqlQuery implements IteratorAggregate {
-
- public $type, $set, $laliasinfo, $osql, $select, $select_unparsed, $from, $from_unparsed, $join, $groupby, $orderby, $limit;
- public $where = array();
- public $table_extra_where = array();
-
- function __construct($osql) {
- $this->osql = $osql;
- }
-
- function __call($method, $args) {
- return call_user_func_array($this->osql->imported_query_functions[$method], array_merge(array($this), $args));
- }
-
- function array_to_oo($rows) {
- $r = array();
- foreach($rows as $row) {
- foreach($this->colmap as $lalias => $colmap) {
- foreach($colmap['maps'] as $from => $to) {
- $row[$lalias][$to] = $row[$from];
- unset($row[$from]);
- }
- $row[$lalias] = call_user_func($colmap['ooinit'], $this->osql->field_serialization($row[$lalias], $colmap['info'], 'unserialize'));
- }
- $r[] = (count($row) == 1 && isset($lalias) ? current($row) : (object)$row);
- }
- return $r;
- }
-
- private function add_class_alias($glalias) {
- if(!isset($this->osql->aliases[$glalias])) {
- if($this->type == 'selectoo' && class_exists($glalias)) {
- $this->osql->aliases[$glalias] = array('class' => $glalias);
- } else {
- return;
- }
- }
- $curaliasinfo = $this->osql->aliases[$glalias];
- if($this->type == 'selectoo' && isset($curaliasinfo['class']) && count(array_diff(array('table', 'ooinit', 'classvars'), array_keys($curaliasinfo))) != 0) {
- $this->osql->aliases[$glalias] = array_merge($this->osql->get_class_info($curaliasinfo['class']), $this->osql->aliases[$glalias]);
- }
- }
-
- function getIterator() {
- return $this->getIteratorImpl();
- }
-
- function count() {
- return $this->select('COUNT(*)');
- }
-
- function select($select_unparsed = null) {
- if(is_null($select_unparsed)) {
- return $this->select_unparsed;
- }
- if($this->type === 'selectoo') {
- return $this->selectoo($select_unparsed);
- }
- $this->type = 'select';
- $this->select_unparsed = $select_unparsed;
- $this->select = null;
- return $this;
- }
-
- function selectoo($select_unparsed = null) {
- if(is_null($select_unparsed)) {
- return $this->select_unparsed;
- }
- if($this->type === 'select') {
- return $this->select($select_unparsed);
- }
- $this->type = 'selectoo';
- $this->select_unparsed = $select_unparsed;
- $this->select = null;
- return $this;
- }
-
- function parse_select_replace($matches) {
- if($matches[1] == '*') {
- $replacements = array();
- foreach($this->laliasinfo as $info) {
- $replacement = $this->parse_select_replace(array(false, $info['lalias'], ''));
- if($replacement === false && (!isset($replacements[0]) || $replacements[0] !== '*')) {
- $replacements = array_merge(array('*'), $replacements);
- } else if($replacement !== false) {
- $replacements[] = $replacement;
- }
- }
- return implode(', ', $replacements) . (count($replacements) > 0 ? $matches[2] : '');
- }
-
- $laliasinfo = $this->laliasinfo[$matches[1]];
- $classname = isset($laliasinfo['class']) ? $laliasinfo['class'] : null;
-
- if(isset($laliasinfo['columns'])) {
- $columns = $laliasinfo['columns'];
- } else if($this->type == 'selectoo' && !is_null($classname)) {
- if(!isset($this->osql->aliases[$classname]['classvars'])) {
- $this->add_class_alias($classname);
- }
- $columns = $this->osql->aliases[$classname]['classvars'];
- } else if($this->type == 'selectoo' && class_exists($laliasinfo['glalias'])) {
- $classname = $laliasinfo['glalias'];
- $this->add_class_alias($classname);
- $this->osql->aliases[$classname];
- $laliasinfo = $this->laliasinfo[$matches[1]] = array_merge($laliasinfo, $this->osql->aliases[$classname]);
- $columns = $this->osql->aliases[$classname]['classvars'];
- // TODO: make test 4 this case
- } else {
- return $matches[0];
- }
-
- $colmap = $newselect = array();
- foreach($columns as $defaultcol) {
- $newselect[] = "`{$laliasinfo['lalias']}`.`$defaultcol` AS `{$laliasinfo['lalias']}_$defaultcol`";
- $colmap["{$laliasinfo['lalias']}_$defaultcol"] = $defaultcol;
- }
- $ooinit = isset($laliasinfo['ooinit']) ? $laliasinfo['ooinit'] : create_function('$a', 'return (object)$a;');
- $this->colmap[$laliasinfo['lalias']] = array('maps' => $colmap, 'ooinit' => $ooinit, 'info' => $laliasinfo);
- return implode(', ', $newselect) . (count($newselect) > 0 ? $matches[2] : '');
- }
-
- function parse_select() {
- if(!is_null($this->select)) {
- return;
- }
- $this->colmap = array();
- $this->select = $this->select_unparsed;
- $strsplit = preg_split('/(["\'])(?:\\\\?.)*?\1/', $this->select_unparsed, -1, PREG_SPLIT_OFFSET_CAPTURE);
- $shift = 0;
- foreach($strsplit as $offset) {
- $repl = preg_replace_callback('/%([^ ,()]+)\s*(,|$)/', array($this, 'parse_select_replace'), substr($this->select, $offset[1] + $shift, strlen($offset[0])));
- $this->select = substr_replace($this->select, $repl, $offset[1] + $shift, strlen($offset[0]));
- $shift += strlen($repl) - strlen($offset[0]);
- }
- }
-
- function update($from = null) {
- if(is_null($from)) {
- return $this->from;
- }
- $this->type = 'update';
- $this->from = $from;
- return $this;
- }
-
- function from($from_unparsed = null) {
- if(is_null($from_unparsed)) {
- return $this->from_unparsed;
- }
- $this->from_unparsed = $from_unparsed;
- $this->from = null;
- return $this;
- }
-
- function parse_from() {
- if(!is_null($this->from)) {
- return;
- }
- $tablearr = preg_split('/(\s+|,|-|\(|\))/', $this->from_unparsed, -1, PREG_SPLIT_DELIM_CAPTURE);
- $tablearr = array_values(array_filter(array_map('trim', $tablearr), 'strlen'));
- $this->from = array();
- $this->laliasinfo = array();
-
- $parentstack = array();
- $from = null;
- while(($curstr = current($tablearr)) !== false) {
- $curstr = trim($curstr, '`');
- $connection = isset($this->osql->connections["{$from['glalias']},$curstr"]) ? $this->osql->connections["{$from['glalias']},$curstr"] : null;
- $connection = is_null($connection) && isset($this->osql->connections["{$from['table']},$curstr"]) ? $this->osql->connections["{$from['table']},$curstr"] : $connection;
- if(!is_null($from)) {
- $to = array('table' => $connection['table'], 'glalias' => $connection['glalias'], 'field' => $curstr, 'lalias' => $curstr);
- } else {
- $to = array('table' => $curstr, 'glalias' => $curstr, 'lalias' => $curstr);
- }
- $this->add_class_alias($to['glalias']);
- $to = isset($this->osql->aliases[$to['glalias']]) ? array_merge($to, $this->osql->aliases[$to['glalias']]) : $to;
- $curstr = next($tablearr) == 'AS' ? next($tablearr) : current($tablearr);
- if($curstr !== false && strpos('(,-)', $curstr) === false) {
- $to['lalias'] = trim($curstr, '`');
- $curstr = next($tablearr);
- }
-
- if(isset($to['where'])) {
- $this->table_extra_where[] = str_replace("%{$to['glalias']}%", $to['lalias'], $to['where']);
- }
-
- $tablestr = ($to['table'] == $to['lalias'] ? "`{$to['table']}`" : "`{$to['table']}` AS `{$to['lalias']}`");
- $this->laliasinfo[$to['lalias']] = $to;
- if(is_null($from)) {
- $this->from[] = (count($this->from) == 0 ? '' : ',') . $tablestr;
- } else {
- $joinon = str_replace(array("%{$from['glalias']}%", "%{$from['table']}%", "%{$to['field']}%"), array($from['lalias'], $from['lalias'], $to['lalias']), $connection['sqljoin']);
- $this->from[] = "{$connection['extra']['jointype']} JOIN $tablestr ON $joinon";
- }
-
- while(strpos('(,-)', $curstr) !== false) {
- if($curstr == '(') {
- $parentstack[] = $to;
- } else if($curstr == ')') {
- array_pop($parentstack);
- } else if($curstr == '-') {
- $from = $to;
- } else if($curstr == ',') {
- $from = count($parentstack) == 0 ? null : $parentstack[count($parentstack) - 1];
- }
- $curstr = next($tablearr);
- }
- }
- $this->from = implode(' ', $this->from);
- }
-
- function join($join = null) {
- if(is_null($join)) {
- return $this->join;
- }
- $this->join = $join;
- return $this;
- }
-
- function set($set = null) {
- if(is_null($set)) {
- return $this->set;
- }
- $this->set = $set;
- return $this;
- }
-
- function where($where = null) {
- if(is_null($where)) {
- return '(' . implode(') AND (', $this->where) . ')';
- }
- $this->where = func_get_args();
- $this->where = $this->osql->array_flatten($this->where);
- return $this;
- }
-
- function andwhere($where) {
- $func_args = func_get_args();
- $this->where = array_merge($this->osql->array_flatten($func_args), $this->where);
- return $this;
- }
-
- function orwhere($where) {
- $func_args = func_get_args();
- $this->where = array('((' . implode(') AND (', $this->where) . ')) OR (' . implode(') OR (', $this->osql->array_flatten($func_args)) . ')');
- return $this;
- }
-
- function groupby($groupby = null) {
- if(is_null($groupby)) {
- return $this->groupby;
- }
- $this->groupby = $groupby;
- return $this;
- }
-
- function orderby($orderby = null) {
- if(is_null($orderby)) {
- return $this->orderby;
- }
- $this->orderby = $orderby;
- return $this;
- }
-
- function limit($start = null, $length = null) {
- if(is_null($start)) {
- return $this->limit;
- }
- $start = strpos($start, ',') !== false ? explode(',', $start) : $start;
- if(is_array($start)) {
- list($start, $length) = array_merge($start, array(null));
- }
- $this->limit = is_null($length) ? (string)$start : "$start,$length";
- return $this;
- }
-
- function sql() {
- if($this->type == 'select' || $this->type == 'selectoo') {
- $this->parse_from();
- $this->parse_select();
- $sql[] = "SELECT $this->select FROM $this->from";
- } else if($this->type == 'update') {
- $from = $this->osql->glalias2table(trim(str_replace('`', '', $this->from)));
- $sql[] = "UPDATE `$from` SET $this->set";
- }
- if(!is_null($this->join)) {
- $sql[] = $this->join;
- }
- $where = array_merge($this->table_extra_where, $this->where);
- if(count($where) != 0) {
- $sql[] = 'WHERE (' . implode(') AND (', $where) . ')';
- }
- if(!is_null($this->groupby)) {
- $sql[] = "GROUP BY {$this->groupby}";
- }
- if(!is_null($this->orderby)) {
- $sql[] = "ORDER BY {$this->orderby}";
- }
- if(!is_null($this->limit)) {
- $sql[] = "LIMIT {$this->limit}";
- }
- return implode(' ', $sql);
- }
-
- function __toString() {
- return $this->sql();
- }
- }
-
- ?>