* @package Mammut\DB\Model */ class ViewInfo extends \Mammut\StrictObject implements XMLModel { /** * @var string */ private $name = ""; private $base = false; /** * @var array */ private $columns = array(); private $joins = array(); public function __construct($name) { $this->name = $name; } public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } public function getBase() { return $this->base; } public function setBase($name) { $this->base = $name; } public function getColumnCount() { return count($this->columns); } public function addColumn($base, $name, $alias = false) { if($alias === false) $alias = $name; foreach($this->columns as $cname=>$values) { if($cname == $alias) throw new \InvalidArgumentException("dublicate column name: " . $alias); } $this->columns[$alias] = array('type' => 'default', 'base' => $base,'basecolumn' => $name); } /** * Defines a calculated column based on a expression * @param iExpression $expression * @param string $name * @throws \InvalidArgumentException */ public function addVirtualColumn(iExpression $expression, $name) { if(empty($name)) throw new \InvalidArgumentException("missing column name"); foreach($this->columns as $cname=>$values) { if($cname == $name) throw new \InvalidArgumentException("dublicate column name: " . $name); } $this->columns[$alias] = array('type' => 'virtual', 'expression' => $expression); } /** * Defines a column which has a fixed value * @param mixed $value the column name * @param string $name the column name * @throws \InvalidArgumentException */ public function addFixColumn($value, $name) { if(empty($name)) throw new \InvalidArgumentException("missing column name"); foreach($this->columns as $cname=>$values) { if($cname == $name) throw new \InvalidArgumentException("dublicate column name: " . $name); } $this->columns[$alias] = array('type' => 'fix', 'value' => $value); } /** * returns the info object of a specific column * * @param mixed $col * the column name or index * @return ColumnInfo */ public function getColumnInfo($col) { // echo "seaching colinfo for $col\n"; if(is_int($col)) { $keys = array_keys($this->columns); $col = $keys[$col]; // echo "seaching colinfo for $col\n"; } if(empty($this->columns[$col])) throw new \InvalidArgumentException("invalid column index"); return $this->columns[$col]; } /** * searches the number of a given column name * * @param $name string * the name of the column * @return int the column number or -1 if none was found with the name given */ public function getColumnNum($name) { $c = count($this->columns); for($i = 0; $i < $c; $i++) { if($this->columns[$i]->getName() == $name) return $i; } return -1; } public function delColumn($id) { if(is_int($id)) { $new = array(); for($i = 0; $i < $id; $i++) { $new[] = $this->columns[$i]; } for($i = $id + 1; $i < count($this->columns); $i++) { $new[] = $this->columns[$i]; } unset($this->columns); $this->columns = $new; } else { $i = 0; while(isset($this->columns[$i]) && ($this->columns[$i]->getName() != $id)) $i++; if(isset($this->columns[$i])) $this->delColumn((int) $i); } } public function addJoinCondition($base, $type, $conds) { $this->joins[$base] = array('type' => $type,'cond' => $conds); } public function getJoinObjects() { return array_keys($this->joins); } public function getJoinInfo($name) { return $this->joins[$name]; } public function compareTo(ViewInfo $otherInfo) { $colMismatch = array(); $toremove = array(); $missing = array(); for($i = 0; $i < $this->getColumnCount(); $i++) { $c1 = $this->getColumnInfo($i); $found = false; for($j = 0; $j < $otherInfo->getColumnCount(); $j++) { $c2 = $otherInfo->getColumnInfo($j); if($c1->getName() == $c2->getName()) { $mismatch = array(); if($c1->getType() != $c2->getType()) { $equal = false; $mismatch['type'] = array( 'this' => $c1->getType(),'other' => $c2->getType()); } elseif($c1->getType() == ColumnInfo::TYPE_ENUM) { foreach($c1->getParam() as $e) { if(preg_match('#values\(([a-zA-Z0-9_,]*)\)#', $e, $match)) { $values1 = explode(',', $match[1]); break; } } foreach($c2->getParam() as $e) { if(preg_match('#values\(([a-zA-Z0-9_,]*)\)#', $e, $match)) { $values2 = explode(',', $match[1]); break; } } if(count(array_diff($values1, $values2)) != 0) { $equal = false; $mismatch['enum'] = array('this' => $values1,'other' => $values2); } } if($c1->getSize() != $c2->getSize() && ($c1->getType() == ColumnInfo::TYPE_CHAR || $c1->getType() == ColumnInfo::TYPE_VCHAR || $c1->getType() == ColumnInfo::TYPE_BINARY)) { $equal = false; $mismatch['size'] = array( 'this' => $c1->getSize(),'other' => $c2->getSize()); } $found = true; if(count($mismatch) > 0) $colMismatch[$c1->getName()] = $mismatch; } } if(!$found) { array_push($missing, $c1->getName()); $equal = false; } } for($i = 0; $i < $otherInfo->getColumnCount(); $i++) { $c1 = $otherInfo->getColumnInfo($i); $found = false; for($j = 0; $j < $this->getColumnCount(); $j++) { $c2 = $this->getColumnInfo($j); if($c1->getName() == $c2->getName()) $found = true; } if(!$found) { array_push($toremove, $c1->getName()); $equal = false; } } $result = new \stdClass(); if(count($missing) > 0) $result->missingColumns = $missing; if(count($colMismatch) > 0) $result->differentColumns = $colMismatch; if(count($toremove) > 0) $result->additionalColumns = $toremove; return $result; } public static function fromXML($data) { if($data instanceof \SimpleXMLElement) $xml = $data; else $xml = simplexml_load_string((string) $data); $result = new ViewInfo((string) $xml['name']); $result->setBase((string) $xml['base']); // add base columns foreach($xml->vcolumn as $c) { $result->addColumn($result->getBase(), (string) $c['column'], (string) $c['alias']); } // add additional columns foreach($xml->join as $j) { $type = (string) $j['type']; $base = (string) $j['base']; foreach($j->vcolumn as $c) { $result->addColumn($base, (string) $c['column'], (string) $c['alias']); } } foreach($xml->join as $j) { $type = (string) $j['type']; $base = (string) $j['base']; $conds = array(); foreach($j->condition as $c) { $con = (string) $c; if(preg_match('#^([a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+))?([<>=!]{1,3})([a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+))?$#', $con, $match)) { $conds[] = array( 'left' => $match[1],'operator' => $match[3],'right' => $match[4]); } else throw new \Exception("unparsable condition: {$con}"); } $result->addJoinCondition($base, $type, $conds); } return $result; } public function toXML() { $xml = 'name . '"'; $xml .= ' transaction="' . ($this->transactionSave ? 'true' : 'false') . '"'; $xml .= '>'; $xml .= '' . implode(',', $this->primary) . ''; foreach($this->indexes as $name=>$fields) $xml .= '' . implode(',', $fields) . ''; foreach($this->columns as $c) $xml .= $c->toXML(); $xml .= ''; return $xml; } }