/** * Get normality tags */ public function getTags($type = 'normality') { return \Bond\extract_tags($this->comment, $type); }
/** * 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 testExtractTagsObject() { $key = 'form'; $value = 'sometagtext'; $obj = new extractTagsObject($key, $value); $this->assertSame(\Bond\extract_tags($obj), array($key => $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; }
/** * Form choice text function * @return array $lines */ private function getFormChoiceTextFunction() { // default function only works for tables with a lone primary key $columns = $this->pgClass->getAttributes(); // find columns tagged 'form-choicetext' $columnsSelected = array(); foreach ($columns as $column) { $tags = \Bond\extract_tags($column, 'normality'); if (isset($tags['form-choicetext'])) { $columnsSelected[] = $column; } } switch (count($columnsSelected)) { case 0: return; case 1: $columnName = array_pop($columnsSelected)->name; break; default: throw new \FormChoiceTextConfigurationException("Multiple columns with tag 'form-choicetext'. Only one column per table can have this tag."); } $this->class->classComponents[] = new FunctionDeclaration('form_choiceText', new Sformatf(<<<'PHP' /** * Function called by \Bond\Bridge\Normality\Form\Type\Normality when displaying text for this entity * @return scalar */ public function form_choiceText() { return $this->get('%s'); } PHP , addslashes($columnName))); }