function render() { // Validate defaultParam's value. $def = $this->getDefaultParam(); if (!empty($def)) { if (!$this->props->defines($def)) { throw new ComponentException($this, "Invalid value for <kbd>defaultParam</kbd> on <b><{$this->props->macro}></b>; parameter <kbd>{$def}</kbd> does not exist"); } // Move children to default parameter. if ($this->hasChildren()) { $type = $this->props->getTypeOf($def); if ($type != type::content && $type != type::metadata) { throw new ComponentException($this, sprintf("The macro's default parameter <kbd>{$def}</kbd> can't hold content because its type is <kbd>%s</kbd>.", type::getNameOf($type))); } $param = new Metadata($this->context, ucfirst($def), $type); $this->props->set($def, $param); $param->attachTo($this); $param->setChildren($this->getChildren()); } } elseif ($this->hasChildren()) { throw new ComponentException($this, 'You may not specify content for this tag because it has no default property'); } parent::render(); }
/** * Returns the value converted to a the data type required by the specified property. * * @param string $name * @param mixed $v * @return bool|float|int|null|string|\Traversable * @throws ComponentException */ function typecastPropertyValue($name, $v) { if ($this->isScalar($name) && $this->isEnum($name)) { $this->validateEnum($name, $v); } $type = $this->getTypeOf($name); if ($type && !type::validate($type, $v)) { throw new ComponentException($this->component, sprintf("%s is not a valid value for the <kbd>{$name}</kbd> property, which is of type <kbd>%s</kbd>", is_scalar($v) ? sprintf("The %s<kbd>%s</kbd>", typeOf($v), var_export($v, true)) : sprintf("A value of PHP type <kbd>%s</kbd>", typeOf($v)), type::getNameOf($type))); } // A special case for content type properties: // Convert a content property specified as attribute=string to a format equivalent to the one generated by // <subtag>string</subtag> if ($type == type::content && is_string($v)) { $content = new Metadata($this->component->context, $name, type::metadata); $content->setChildren([Text::from($this->component->context, $v)]); return $content; } return type::typecast($type, $v); }