Example #1
0
 public function export()
 {
     $a = parent::export();
     $a['@tag'] = $this->getTagName();
     $a['@type'] = $this->type;
     return $a;
 }
Example #2
0
 /**
  * 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
 }
Example #4
0
 /**
  * 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>&lt;<b>{$prefix}:</b>{$tagName}&gt;</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);
         }
     }
 }
Example #8
0
 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);
         }
     }
 }
Example #9
0
 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>&lt;{$parent->getTagName()}></b>, of type <b>{$parent->className}</b>\n</table>\n");
 }
Example #10
0
 /**
  * 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);
 }
Example #13
0
 protected function evalBinding(Expression $exp)
 {
     return _e(parent::evalBinding($exp));
 }
Example #14
0
 /**
  * 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;
 }