/** * Coearce passed value to type stored in $this->type. * The output of this function is expected to be passed to QuoteInterface->quote() * * @param mixed Value to coearce to type * @return mixed */ private function coearceToType($value) { // objects have to support QueryQuoteSafe if (is_object($value)) { if ($value instanceof SqlInterface) { return $value; } throw new BadTypeException($value, "Needs to implement SqlInterface"); // null's don't get molested } elseif ($value === null) { return null; } $isArray = is_array($value); // We're told to expect a array and we don't get one ... if ($this->isArray and !$isArray) { throw new BadTypeException($value, 'array'); } // Have array ... if (is_array($value)) { // build a element modifier for the elenents in our array $elementModifier = clone $this; if (in_array($this->type, ['in', 'array'], true)) { $elementModifier->type = null; } $elementModifier->isArray = false; // coearce every value in the array to to the correct type $value = array_map(array($elementModifier, 'coearceToType'), $value); $class = sprintf("%s\\%sType", __NAMESPACE__, $this->type === 'in' ? 'In' : 'Array'); return new $class($value); } // standard types switch ($this->type) { case null: return $value; case 'text': case 'enum': case 'timestamp': return (string) $value; case 'bool': return \Bond\boolval($value); case 'oid': case 'int': return (int) $value; case 'identifier': return new Identifier($value); case 'json': return is_string($value) ? $value : json_encode($value); case 'varbit': return decbin((int) $value); case 'bytea': return new Bytea($value); } // char(13) if (preg_match('/^char\\(([\\d]+)\\)$/', $this->type, $matches)) { return (string) substr($value, 0, $matches[1]); } return $value; }
/** * Get a postgres runtime parameter * @return string */ public function getParameter($parameter) { self::isParameterAllowed($parameter); $value = $this->query(new Raw("SHOW {$parameter}"))->fetch(Result::FETCH_SINGLE); return ($value === 'true' or $value === 'false') ? \Bond\boolval($value) : $value; }
/** * Extract tags from string * * Tags beginning with %tag: [1,2,3] are json decoded * Tags beginning with @tag: value are build in the stanard way * Tags can be 'namespaced' with '.' * * @param string|object String from which to extract comments. If object it must expose ->getComment(). // If you want inheritance it must expose ->getReferences() * @return array Comments */ function extract_tags($stringOrObject, $prefix = null) { // object handling if (is_object($stringOrObject)) { if (method_exists($stringOrObject, 'getComment')) { $string = $stringOrObject->getComment(); } else { throw new BadTypeException($stringOrObject, 'string'); } } else { $string = (string) $stringOrObject; } $regex = "/^\n ([%@\$])\n ([^\\v:\\[\\]]+)\n (\\[\n [^\\]]*\n \\])?\n :\n (.*)?\n \$\n |\n ^\n ([%@])\n (.*)\n \$\n /mx"; $output = array(); if (preg_match_all($regex, $string, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { // we got a lone tag no value if (isset($match[6])) { $match[2] = $match[6]; $match[4] = 'true'; } $key = trim($match[2]); $value = trim($match[4]); // Namespacing. F*****g hell these were 6 very difficult lines. Be afraid. Seriously. I'm not joking. $working = array(); $refs = array(); $keys = explode('.', $key); foreach (array_reverse($keys) as $k) { $working = array($k => $working); $refs[] =& $working[$k]; } // inheritance? if ($value === '@inherit') { throw new \Exception("TODO"); if (!is_object($stringOrObject)) { throw new \LogicException("can't inherit off object which doesn't reference another object, see object->get('references')"); } // merge only the tags which are required if ($reference = $stringOrObject->get('references')) { $value = \Bond\extract_tags($reference); foreach ($keys as $key) { // no match if (!is_array($value) || !array_key_exists($key, $value)) { // break reference chain. This loop will now do nothing. $working = array(); } else { $value = $value[$key]; } } } else { // break reference chain. This loop will now do nothing. $working = array(); } } // json decode if ($match[1] === '%') { $value = json_decode($value, true); if (json_last_error()) { throw new \UnexpectedValueException("json_decode returned a error when extracting tags `{$value}` in \n `{$string}`\n"); } } elseif ($match[1] === '$') { $value = call_user_func($value); } // cast bool-like strings and nulls to their real types if (is_string($value)) { if (in_array(strtolower($value), array('t', 'f', 'true', 'false', 'on', 'off'))) { $value = \Bond\boolval($value); } elseif ($value === 'NULL') { $value = 'spanner'; } } // is array() if (!empty($match[3])) { if ($match[3] == '[]') { $refs[0][] = $value; } else { $key = trim($match[3], '[]'); $refs[0][$key] = $value; } } else { $refs[0] = $value; } // merge working into output $output = array_merge_recursive($output, $working); } } // prefix namespace aware if (isset($prefix)) { foreach (explode('.', $prefix) as $key) { if (!is_array($output) || !array_key_exists($key, $output)) { return array(); } else { $output = $output[$key]; } } } return $output; }
/** * Generate a dataType from a Bond\Pg\Catalog\PgAttribute * @param Attribute $attribute * @return static */ public static function makeFromAttribute(PgAttribute $attribute) { $name = $attribute->name; $entity = $attribute->getRelation()->getEntityName(); $type = $attribute->getType(); $fullyQualifiedName = $attribute->getFullyQualifiedName(); $data = array('isPrimaryKey' => $attribute->isPrimaryKey(), 'isUnique' => $attribute->isUnique(), 'isNullable' => !$attribute->notNull, 'isArray' => $attribute->isArray, 'isInherited' => $attribute->isInherited(), 'type' => $type->getTypeQuery(), 'length' => $attribute->length, 'default' => $attribute->default); $data += $attribute->getEntity(); if ($type->isBool() and in_array(strtolower($data['default']), array('true', 'false'))) { $data['default'] = \Bond\boolval($data['default']); } if ($type->isEnum()) { $data['enumName'] = $type->name; } if ($tags = \Bond\extract_tags($attribute->comment, 'form')) { $data['form'] = $tags; } if ($tags = \Bond\extract_tags($attribute->comment, 'api')) { $data += $tags; } if ($tags = \Bond\extract_tags($attribute->comment, 'filter')) { $data['filter'] = $tags; } if ($tags = \Bond\extract_tags($attribute->comment, 'normality')) { $data['isFormChoiceText'] = isset($tags['form-choicetext']); $data['isAutoComplete'] = isset($tags['autoComplete']); } return new static($name, $entity, $fullyQualifiedName, $data); }
public function testBoolval() { $this->assertTrue(\Bond\boolval(true)); $this->assertTrue(\Bond\boolval(1)); $this->assertTrue(\Bond\boolval('true')); $this->assertTrue(\Bond\boolval('TRUE')); $this->assertTrue(\Bond\boolval('True')); $this->assertTrue(\Bond\boolval('tTuE')); $this->assertTrue(\Bond\boolval('spanner')); $this->assertTrue(\Bond\boolval('t')); $this->assertTrue(\Bond\boolval('T')); $this->assertFalse(\Bond\boolval(false)); $this->assertFalse(\Bond\boolval(null)); $this->assertFalse(\Bond\boolval(0)); $this->assertFalse(\Bond\boolval('false')); $this->assertFalse(\Bond\boolval('fAlSE')); $this->assertFalse(\Bond\boolval('False')); $this->assertFalse(\Bond\boolval('f')); $this->assertFalse(\Bond\boolval('F')); }