public function export() { $a = parent::export(); $a['@tag'] = $this->getTagName(); $a['@type'] = $this->type; return $a; }
/** * Renders the block contents. * * @return string */ public function render() { $out = ''; for ($i = 0, $c = count($this->contents); $i < $c; ++$i) { $content = $this->contents[$i]; $out .= is_string($content) ? $content : Component::getRenderingOfSet($content); } return $out; }
/** * Allows subclasses to generate the view's markup dinamically. * If not overridden, the default behaviour is to render the view previously set by {@see createView}. * * ><p>**Note:** this returns nothing; the output is sent directly to the output buffer. */ protected function render() { if ($this->view) { // The view model is sent to render() because the view may not be a Matisse template, in which case the model must // be set explicitly. echo $this->view->render($this->getViewModel()); } elseif ($this->shadowDOM) { $this->shadowDOM->run(); } // Otherwise, do NOT render the component's content }
/** * Replaces the component by the specified componentes in the parent's child list. * The component itself is discarded from the components tree. * * @param array $components * @throws ComponentException */ public function replaceBy(array $components = null) { $p = $this->getIndex(); if ($p !== false) { array_splice($this->parent->children, $p, 1, $components); $this->parent->attach($components); } else { $t = ComponentInspector::inspectSet($this->parent->children); throw new ComponentException($this, "The component was not found on the parent's children.<h3>The children are:</h3><fieldset>{$t}</fieldset>"); } }
/** * Creates a component corresponding to the specified tag and optionally sets its published properties. * * <p>This is called by the parser. * * @param string $tagName It may contain an XML namespace prefix, ex: 'x:tag' * @param Component $parent The component's container component. * @param string[] $props A map of property names to property values. * Properties specified via this argument come only from markup attributes, not * from subtags. * @param array|null $bindings A map of attribute names and corresponding databinding expressions. * @param bool $generic If true, an instance of GenericComponent is created. * @param boolean $strict If true, failure to find a component class will throw an exception. * If false, an attempt is made to load a macro with the same name, * @return Component Component instance. For macros, an instance of Macro is returned. * @throws ComponentException * @throws MatisseException */ function createComponentFromTag($tagName, Component $parent, array $props = null, array $bindings = null, $generic = false, $strict = false) { $s = explode(':', $tagName, 2); if (count($s) > 1) { list($prefix, $tagName) = $s; } else { $prefix = ''; } if ($prefix) { throw new MatisseException("XML namespaces are not yet supported.<p>Tag: <kbd><<b>{$prefix}:</b>{$tagName}></kbd>"); } if ($generic) { $component = new GenericHtmlComponent($tagName, $props); return $component; } $class = $this->getClassForTag($tagName); /** @var DocumentContext $this */ if (!$class) { if ($strict) { Component::throwUnknownComponent($this, $tagName, $parent); } // Component class not found. // Convert the tag to a MacroInstance component instance that will attempt to load a macro with the same // name as the tag name. if (is_null($props)) { $props = []; } $props['macro'] = $tagName; $component = new MacroCall(); } else { $component = $this->injector->make($class); } // For both types of components: if (!$component instanceof Component) { throw new ComponentException(null, sprintf("Class <kbd>%s</kbd> is not a subclass of <kbd>Component</kbd>", get_class($component))); } $component->setTagName($tagName); return $component->setup($parent, $this, $props, $bindings); }
private static function inspectViewModel(Component $component) { return; // DISABLED $old = DebugConsole::$settings->tableUseColumWidths; DebugConsole::$settings->tableUseColumWidths = false; echo $component->getDataBinder()->inspect(); DebugConsole::$settings->tableUseColumWidths = $old; }
/** * Assign a new owner to the properties object. This will also do a deep clone of the component's properties. * * @param Component $owner */ function setComponent(Component $owner) { $this->component = $owner; $props = $this->getPropertiesOf(type::content); foreach ($props as $name => $value) { if (!is_null($value)) { /** @var Component $c */ $c = clone $value; $c->attachTo($owner); $this->{$name} = $c; } } $props = $this->getPropertiesOf(type::collection); foreach ($props as $name => $values) { if (!empty($values)) { $this->{$name} = Component::cloneComponents($values, $owner); } } }
protected function init() { parent::init(); $assets = $this->context->getAssetsService(); foreach ($this->props->style as $style) { if ($style->props->src) { $assets->addStylesheet($style->props->src); } else { $assets->addInlineCss($style->runAndGetContent(), $style->props->name); } } }
static function throwUnknownComponent(DocumentContext $context, $tagName, Component $parent, $filename = null) { $paths = implode('', map($context->matisseSettings->getMacrosDirectories(), function ($dir) { return "<li><path>{$dir}</path></li>"; })); $filename = $filename ? "<kbd>{$filename}</kbd>" : "it"; throw new ComponentException(null, "<h3>Unknown component / macro: <b>{$tagName}</b></h3>\n<p>Neither a <b>class</b>, nor a <b>property</b>, nor a <b>macro</b> with the specified name were found.\n<p>If it's a component, perhaps you forgot to register the tag...\n<p>If it's a macro, Matisse is searching for {$filename} on these paths:<ul>{$paths}</ul>\n<table>\n <th>Container component:<td><b><{$parent->getTagName()}></b>, of type <b>{$parent->className}</b>\n</table>\n"); }
/** * Merges adjacent Text children of the specified container whenever that merge can be safely done. * * > Note: Although the parser doesn't generate redundant literals, they may occur after macro substitutions are * performed. * * @param Component $c The container component. */ private function text_optimize(Component $c) { $o = []; $prev = null; if ($c->hasChildren()) { foreach ($c->getChildren() as $child) { if ($prev && $prev instanceof Text && !$prev->getBindings() && $child instanceof Text && !$child->getBindings()) { // safe to merge $prev->props->value .= $child->props->value; continue; } $o[] = $child; $prev = $child; } } $c->setChildren($o); }
protected function render() { $prop = $this->props; $isMultiple = $prop->multiple; $assets = $this->context->getAssetsService(); $assets->addInlineScript("selenia.ext.select.props['{$prop->id}']=" . JavascriptCodeGen::makeOptions(['autoOpenLinked' => $prop->autoOpenLinked, 'dataUrl' => $prop->dataUrl, 'emptyLabel' => $prop->emptyLabel, 'emptySelection' => $prop->emptySelection, 'id' => $prop->id, 'labelField' => $prop->labelField, 'linkedSelector' => $prop->linkedSelector, 'linkedUrl' => $prop->linkedUrl, 'multiple' => $prop->multiple, 'noResultsText' => $prop->noResultsText, 'valueField' => $prop->valueField, 'value' => $prop->value])); // If required, add auto-add tag behavior to this Chosen. if ($prop->autoTag && $prop->multiple) { $assets->addInlineScript("\n\$(function () {\n \$ ('#{$prop->id}+.chosen-container .chosen-choices input').on ('keyup', function (ev) { console.log(ev);\n var v = \$ (this).val ();\n if (ev.keyCode == 13 && v) {\n var tags = \$ ('#{$prop->id} option').map (function (i, e) { return \$ (e).val () });\n var found = false, l = v.length;\n tags.each (function (i, x) {\n if (x.substr (0, l) == v) {\n found = true;\n return false\n }\n });\n if (found) return;\n \$ ('#{$prop->id}').append (\"<option>\" + v + \"</option>\");\n \$ ('#{$prop->id}').trigger ('chosen:updated');\n ev.preventDefault ();\n var e = jQuery.Event (\"keyup\");\n e.which = 13;\n \$ ('#{$prop->id}+.chosen-container .chosen-choices input').val (v).trigger ('keyup').trigger (e);\n }\n })\n});\n"); } $this->attr('name', $prop->multiple ? "{$prop->name}[]" : $prop->name); $this->attrIf($isMultiple, 'multiple', ''); $this->attrIf($prop->onChange, 'onchange', $prop->onChange); $this->beginContent(); if ($prop->emptySelection && !$prop->multiple) { $sel = exists($prop->value) ? '' : ' selected'; echo '<option value=""' . $sel . '>' . $prop->emptyLabel . '</option>'; } $viewModel = $prop->get('data'); if (isset($viewModel)) { /** @var \Iterator $dataIter */ $dataIter = iteratorOf($viewModel); $dataIter->rewind(); if ($dataIter->valid()) { $values = $selValue = null; // SETUP MULTI-SELECT if ($isMultiple) { if (isset($prop->value) && !is_iterable($prop->value)) { throw new ComponentException($this, sprintf("Value of multiple selection component must be iterable or null; %s was given.", typeOf($prop->value))); } $it = Flow::from($prop->value); $it->rewind(); $values = $it->valid() && is_scalar($it->current()) ? $it->all() : $it->map(pluck($prop->valueField))->all(); } else { $selValue = strval($prop->get('value')); } // NOW RENDER IT $template = $this->getChildren('listItemTemplate'); $first = true; do { $v = $dataIter->current(); $value = getField($v, $prop->valueField); $label = getField($v, $prop->labelField); if (!strlen($label)) { $label = $prop->emptyLabel; } if ($isMultiple) { $sel = array_search($value, $values) !== false ? ' selected' : ''; } else { if ($first && !$prop->emptySelection && !$prop->multiple && !exists($selValue)) { $prop->value = $selValue = $value; } $eq = $prop->strict ? $value === $selValue : $value == $selValue; if ($eq) { $this->selectedLabel = $label; } $sel = $eq ? ' selected' : ''; } if ($template) { // Render templated list $viewModel['value'] = $value; $viewModel['label'] = $label; Component::renderSet($template); } else { // Render standard list echo "<option value=\"{$value}\"{$sel}>{$label}</option>"; } $dataIter->next(); $first = false; } while ($dataIter->valid()); } } }
protected function inspect(Component $component, $deep = false) { return $component->inspect($deep); }
protected function evalBinding(Expression $exp) { return _e(parent::evalBinding($exp)); }
/** * Checks if the given component matches the preset's selector. * * @param Component $component * @return bool */ function matches(Component $component) { if ($this->matchTag && $this->matchTag !== $component->getTagName()) { return false; } if ($this->matchClass && (!$component instanceof HtmlComponent || !preg_match($this->matchClass, $component->props->class))) { return false; } if ($component->supportsProperties() && ($prop = $this->matchPropName)) { if (!$component->props->defines($prop)) { return false; } if ($this->matchPropValue !== '') { if ($component->props->{$prop} != $this->matchPropValue) { return false; } } else { if (!exists($component->props->{$prop})) { return false; } } } return true; }