/**
  * @param string $className The name of a class that implements {@see ComponentPropertiesInterface}
  * @throws ReflectionException
  */
 function __construct($className)
 {
     if (!implementsInterface($className, ComponentPropertiesInterface::class)) {
         throw new ReflectionException("Class %s does not implement %s", Debug::formatClassName($className), Debug::formatClassName(ComponentPropertiesInterface::class));
     }
     $this->name = $className;
 }
 /**
  * Performs the main execution sequence.
  *
  * @param ServerRequestInterface $request
  * @param ResponseInterface      $response
  * @param callable               $next
  * @return ResponseInterface
  * @throws FatalException
  * @throws FileException
  * @throws FlashMessageException
  */
 function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
 {
     $this->request = $request;
     $this->response = $response;
     $this->initialize();
     //custom setup
     $this->model();
     switch ($this->request->getMethod()) {
         /** @noinspection PhpMissingBreakStatementInspection */
         case 'POST':
             // Perform the requested action.
             $res = $this->doFormAction();
             if ($res) {
                 if ($res instanceof ResponseInterface) {
                     throw new FatalException(sprintf("Invalid HTTP response type: %s<p>Expected: <kbd>ResponseInterface</kbd>", Debug::typeInfoOf($res)));
                 }
                 $response = $res;
             }
             if (!$this->renderOnAction) {
                 if (!$res) {
                     $response = $this->autoRedirect();
                 }
                 break;
             }
         case 'GET':
             // Render the component.
             $out = $this->getRendering();
             $response->getBody()->write($out);
     }
     $this->finalize($response);
     return $response;
 }
Beispiel #3
0
 /**
  * @param string|Component[] $content
  * @return Component[]
  */
 private static function checkContent($content)
 {
     if (!is_array($content) && !is_string($content)) {
         throw new \InvalidArgumentException(sprintf("Block content must be <kbd>string|Component[]</kbd>, %s given", Debug::typeInfoOf($content)));
     }
     return $content;
 }
Beispiel #4
0
 function inspect()
 {
     $VMFilter = function ($k, $v, $o) {
         if ($v instanceof KernelSettings || $v instanceof NavigationInterface || $v instanceof NavigationLinkInterface || $v instanceof SessionInterface || $v instanceof ServerRequestInterface || $v instanceof DocumentContext || $v instanceof Component) {
             return '...';
         }
         return true;
     };
     return _log()->getTable([Debug::getType($this->viewModel) => Debug::RAW_TEXT . _log()->getTable($this->viewModel, '', true, true, 2, $VMFilter), is_null($this->props) ? 'Properties' : Debug::getType($this->props) => Debug::RAW_TEXT . _log()->getTable($this->props, '', true, true, 1, ['props', 'component', 'hidden'])], Debug::getType($this));
 }
Beispiel #5
0
 function __construct($s)
 {
     if (is_null($s)) {
         $this->s = '';
     } elseif ($s instanceof RenderableInterface) {
         $this->s = $s->getRendering();
         return;
     } elseif (!is_string($s)) {
         throw new MatisseException("A <kbd>RawText</kbd> instance must hold a string value, not a " . Debug::typeInfoOf($s));
     }
     $this->s = $s;
 }
 function __call($name, $args)
 {
     $method = "filter_{$name}";
     if (isset($this->filters[$method])) {
         return call_user_func_array($this->filters[$method], $args);
     }
     if (isset($this->fallbackHandler)) {
         if (method_exists($this->fallbackHandler, $method)) {
             return call_user_func_array([$this->fallbackHandler, $method], $args);
         }
     }
     throw new FilterHandlerNotFoundException(sprintf("<p><p>Handler method: <kbd>%s</kbd><p>Arguments: <kbd>%s</kbd>", $method, print_r(map($args, function ($e) {
         return Debug::typeInfoOf($e);
     }), true)));
 }
 /**
  * For internal use.
  *
  * @param Component $component
  * @param bool      $deep
  * @throws ComponentException
  */
 private static function _inspect(Component $component, $deep = true)
 {
     if (self::$recursionMap->contains($component)) {
         echo "<i>recursion</i>";
         return;
     }
     self::$recursionMap->attach($component);
     $COLOR_BIND = '#5AA';
     $COLOR_CONST = '#5A5';
     $COLOR_INFO = '#CCC';
     $COLOR_PROP = '#B00';
     $COLOR_TAG = '#000;font-weight:bold';
     $COLOR_TYPE = '#55A';
     $COLOR_VALUE = '#333';
     $COLOR_SHADOW_DOM = '#5AA;font-weight:bold';
     $Q = "<i style='color:#CCC'>\"</i>";
     $tag = $component->getTagName();
     $hasContent = false;
     echo "<div class=__component><span style='color:{$COLOR_TAG}'>&lt;{$tag}</span>";
     $isDoc = $component instanceof DocumentFragment;
     if (!$component->parent && !$isDoc) {
         echo "&nbsp;<span style='color:{$COLOR_INFO}'>(detached)</span>";
     }
     $type = typeOf($component) . ' #' . Debug::objectId($component);
     echo "<span class='icon hint--rounded hint--right' data-hint='Component:\n{$type}'><i class='fa fa-info-circle'></i></span>";
     $type1 = str_pad('#' . Debug::objectId($component->context), 4, ' ', STR_PAD_LEFT);
     $type2 = str_pad('#' . Debug::objectId($component->getDataBinder()), 4, ' ', STR_PAD_LEFT);
     $type3 = str_pad('#' . Debug::objectId($component->getViewModel()), 4, ' ', STR_PAD_LEFT);
     $type4 = str_pad('#' . Debug::objectId($component->getDataBinder()->getViewModel()), 4, ' ', STR_PAD_LEFT);
     $type5 = str_pad('#' . Debug::objectId($component->getDataBinder()->getProps()), 4, ' ', STR_PAD_LEFT);
     echo "<span class='icon hint--rounded hint--bottom' data-hint='Context:    {$type1}  Data binder:       {$type2}\nView model: {$type3}  Binder view model: {$type4}\nProperties: {$type5}'><i class='fa fa-database'></i></span>";
     // Handle text node
     if ($component instanceof Text) {
         echo "<span style='color:{$COLOR_TAG}'>&gt;</span><div style='margin:0 0 0 15px'>";
         try {
             if ($component->isBound('value')) {
                 /** @var Expression $exp */
                 $exp = $component->getBinding('value');
                 $exp = self::inspectString((string) $exp);
                 echo "<span style='color:{$COLOR_BIND}'>{$exp}</span> = ";
                 $v = self::getBindingValue('value', $component, $error);
                 if ($error) {
                     echo $v;
                     return;
                 }
                 if (!is_string($v)) {
                     echo Debug::typeInfoOf($v);
                     return;
                 }
             } else {
                 $v = $component->props->value;
             }
             $v = strlen(trim($v)) ? HtmlSyntaxHighlighter::highlight($v) : "<i>'{$v}'</i>";
             echo $v;
         } finally {
             echo "</div><span style='color:{$COLOR_TAG}'>&lt;/{$tag}&gt;<br></span></div>";
         }
         return;
     }
     // Handle other node types
     if ($component instanceof DocumentFragment) {
         self::inspectViewModel($component);
     }
     if ($component->supportsProperties()) {
         /** @var ComponentProperties $propsObj */
         $propsObj = $component->props;
         if ($propsObj) {
             $props = $propsObj->getAll();
         } else {
             $props = null;
         }
         if ($props) {
             ksort($props);
         }
         if ($props) {
             $type = typeOf($propsObj);
             $tid = Debug::objectId($propsObj);
             echo "<span class='icon hint--rounded hint--right' data-hint='Properties: #{$tid}\n{$type}'><i class='fa fa-list'></i></span>";
             echo "<table class='__console-table' style='color:{$COLOR_VALUE}'>";
             // Display all scalar properties.
             foreach ($props as $k => $v) {
                 $t = $component->props->getTypeOf($k);
                 $isModified = $component->props->isModified($k);
                 $modifStyle = $isModified ? ' class=__modified' : ' class=__original';
                 if ($t != type::content && $t != type::collection && $t != type::metadata) {
                     $tn = $component->props->getTypeNameOf($k);
                     echo "<tr{$modifStyle}><td style='color:{$COLOR_PROP}'>{$k}<td><i style='color:{$COLOR_TYPE}'>{$tn}</i><td>";
                     // Display data-binding
                     if ($component->isBound($k)) {
                         /** @var Expression $exp */
                         $exp = $component->getBinding($k);
                         $exp = self::inspectString((string) $exp);
                         echo "<span style='color:{$COLOR_BIND}'>{$exp}</span> = ";
                         $v = self::getBindingValue($k, $component, $error);
                         if ($error) {
                             break;
                         }
                     }
                     if (is_null($v)) {
                         echo "<i style='color:{$COLOR_INFO}'>null</i>";
                     } else {
                         switch ($t) {
                             case type::bool:
                                 echo "<i style='color:{$COLOR_CONST}'>" . ($v ? 'true' : 'false') . '</i>';
                                 break;
                             case type::id:
                                 echo "{$Q}{$v}{$Q}";
                                 break;
                             case type::number:
                                 echo $v;
                                 break;
                             case type::string:
                                 echo "{$Q}<span style='white-space: pre-wrap'>" . self::inspectString(strval($v)) . "</span>{$Q}";
                                 break;
                             default:
                                 if (is_object($v)) {
                                     echo sprintf("<i style='color:{$COLOR_CONST}'>%s</i>", Debug::typeInfoOf($v));
                                 } elseif (is_array($v)) {
                                     echo sprintf("<i style='color:{$COLOR_CONST}'>array(%d)</i>", count($v));
                                 } else {
                                     $v = _e($v);
                                     echo "{$Q}{$v}{$Q}";
                                 }
                         }
                     }
                 }
             }
             // Display all slot properties.
             foreach ($props as $k => $v) {
                 $t = $component->props->getTypeOf($k);
                 if ($t == type::content || $t == type::collection || $t == type::metadata) {
                     $tn = $component->props->getTypeNameOf($k);
                     $isModified = $component->props->isModified($k);
                     $modifStyle = $isModified ? ' style="background:#FFE"' : ' style="opacity:0.5"';
                     echo "<tr{$modifStyle}><td style='color:{$COLOR_PROP}'>{$k}<td><i style='color:{$COLOR_TYPE}'>{$tn}</i><td>";
                     /** @var Expression $exp */
                     $exp = $component->getBinding($k);
                     if (isset($exp)) {
                         $exp = self::inspectString((string) $exp);
                         echo "<span style='color:{$COLOR_BIND}'>{$exp}</span> = ";
                         $v = self::getBindingValue($k, $component, $error);
                         if ($error) {
                             echo $v;
                             break;
                         }
                     }
                     if ($v && ($v instanceof Component || is_array($v))) {
                         switch ($t) {
                             case type::content:
                                 if ($v) {
                                     echo "<tr><td><td colspan=2>";
                                     self::_inspect($v, $deep);
                                 } else {
                                     echo "<i style='color:{$COLOR_INFO}'>null</i>";
                                 }
                                 break;
                             case type::metadata:
                                 if ($v) {
                                     echo "<tr><td><td colspan=2>";
                                     self::_inspect($v, $deep);
                                 } else {
                                     echo "<i style='color:{$COLOR_INFO}'>null</i>";
                                 }
                                 break;
                             case type::collection:
                                 echo "of <i style='color:{$COLOR_TYPE}'>", $component->props->getRelatedTypeNameOf($k), '</i>';
                                 if ($v) {
                                     echo "<tr><td><td colspan=2>";
                                     self::_inspectSet($v, true);
                                 } else {
                                     echo " = <i style='color:{$COLOR_INFO}'>[]</i>";
                                 }
                                 break;
                         }
                     } else {
                         if (is_array($v)) {
                             echo "<i style='color:{$COLOR_INFO}'>[]</i>";
                         } else {
                             if (isset($v)) {
                                 printf("<b style='color:red'>WRONG TYPE: %s</b>", Debug::typeInfoOf($v));
                             } else {
                                 echo "<i style='color:{$COLOR_INFO}'>null</i>";
                             }
                         }
                     }
                     echo '</tr>';
                 }
             }
             echo "</table>";
         }
     }
     // If deep inspection is enabled, recursively inspect all children components.
     if ($deep) {
         $content = $shadowDOM = null;
         if ($component->hasChildren()) {
             $content = $component->getChildren();
         }
         if ($component instanceof CompositeComponent) {
             $shadowDOM = $component->provideShadowDOM();
         }
         if ($content || $shadowDOM) {
             echo "<span style='color:{$COLOR_TAG}'>&gt;</span><div style=\"margin:0 0 0 15px\">";
             if ($content) {
                 self::_inspectSet($content, $deep);
             }
             if ($shadowDOM) {
                 echo "<span style='color:{$COLOR_SHADOW_DOM}'>&lt;Shadow DOM&gt;</span><div style=\"margin:0 0 0 15px\">";
                 self::_inspect($shadowDOM, $deep);
                 echo "</div><span style='color:{$COLOR_SHADOW_DOM}'>&lt;/Shadow DOM&gt;</span>";
             }
             echo '</div>';
             $hasContent = true;
         }
     }
     echo "<span style='color:{$COLOR_TAG}'>" . ($hasContent ? "&lt;/{$tag}&gt;<br>" : "/&gt;<br>") . "</span></div>";
 }
 /**
  * Throws an exception if the specified property is not available.
  *
  * @param $propName
  * @throws ComponentException
  */
 function ensurePropertyExists($propName)
 {
     if (!$this->defines($propName)) {
         throw new ComponentException($this->component, sprintf("Invalid property <kbd>%s</kbd> specified for a %s instance.", $propName, Debug::typeInfoOf($this)));
     }
 }
 /**
  * ReflectionPropertyException constructor.
  * @param string $className
  * @param string $propertyName
  * @param string $message
  * @param array  ...$args
  */
 public function __construct($className, $propertyName, $message, ...$args)
 {
     array_push($args, Debug::formatClassName($className), $propertyName);
     parent::__construct(sprintf("{$message}.<p>Property %s-&gt;<kbd>%s</kbd>.", ...$args));
 }
 private function assertContext()
 {
     if (!$this->context) {
         throw new ComponentException($this, sprintf("Can't render the component's template because the rendering context is not set.\n<p>See <kbd>%s</kbd>", Debug::formatClassName(RenderableInterface::class)));
     }
 }
 /**
  * @param mixed $val The value to be inspected.
  * @param mixed $alt If not null, a replacement for inspection; type information about $val is displayed but the
  *                   inspection is performed on this argument instead.
  * @return string
  */
 private function getInspection2($val, $alt = null)
 {
     $arg = $this->table(isset($alt) ? $alt : $val);
     if (is_scalar($val) || is_null($val)) {
         $arg = '<i>(' . Debug::getType($val) . ")</i>{$arg}";
         return "<#data>{$arg}</#data>";
     }
     if ($val instanceof \PowerString) {
         return Debug::toString($val);
     }
     return $this->formatType($val, $arg);
 }
 /**
  * @param \Exception $exception
  * @return string
  */
 private static function getStackTrace($exception)
 {
     ob_start();
     //    $trace = self::filterStackTrace ($exception instanceof PHPError ? debug_backtrace () : $exception->getTrace ());
     $trace = $exception->getTrace();
     if (count($trace) && $trace[count($trace) - 1]['function'] == '{main}') {
         array_pop($trace);
     }
     $count = count($trace);
     foreach ($trace as $k => $v) {
         $class = isset($v['class']) ? $v['class'] : '';
         if ($class == 'ErrorHandler') {
             continue;
         }
         //$class   = $class ? "<span class='class'>$class</span>" : '';
         if (isset($v['function'])) {
             $f = $v['function'];
             $type = isset($v['type']) ? $v['type'] : '->';
             if (strpos($f, '{closure}') !== false) {
                 if ($class) {
                     $fn = "<span class='info' title='On class {$class}'>Closure</span>";
                 } else {
                     $fn = "<span class='type'>Closure</span>";
                 }
             } else {
                 if ($class) {
                     $z = explode('\\', $class);
                     $className = array_pop($z);
                     $namespace = implode('\\', $z);
                     $fn = $f == '__construct' ? "new <span class='class' title='{$namespace}'>{$className}</span>" : "<span class='class' title='{$namespace}'>{$className}</span>{$type}<span class='fn'>{$f}</span>";
                 } else {
                     $fn = "<span class='fn'>{$f}</span>";
                 }
             }
             $fn = "Call {$fn}";
         } else {
             $fn = 'global scope';
         }
         if (isset($v['function'])) {
             $args = [];
             if (isset($v['args'])) {
                 foreach ($v['args'] as $arg) {
                     switch (gettype($arg)) {
                         case 'boolean':
                             $arg = $arg ? 'true' : 'false';
                             break;
                         case 'string':
                             $arg = mb_strlen($arg) > self::TRIM_WIDTH ? sprintf("'<span class='string hint--rounded hint--top' data-hint='%s'>%s</span>'", htmlspecialchars(mb_strimwidth(chunk_split($arg, self::TRIM_WIDTH, "\n"), 0, self::TOOLTIP_MAX_LEN, "..."), ENT_QUOTES), htmlspecialchars(mb_strimwidth($arg, 0, self::TRIM_WIDTH, "..."))) : sprintf("'<span class='string'>%s</span>'", htmlspecialchars($arg, ENT_QUOTES));
                             break;
                         case 'integer':
                         case 'double':
                             break;
                         case 'array':
                             $arg = '<span class="info __type hint--rounded hint--top" data-hint="' . ($arg ? "[\n  " . htmlspecialchars(implode(",\n  ", array_map(function ($k, $v) use($arg) {
                                 return "{$k} => " . self::debugVal($v);
                             }, array_keys($arg), $arg))) . "\n]" : 'Empty array') . '">array</span>';
                             break;
                         default:
                             if (is_object($arg)) {
                                 switch (get_class($arg)) {
                                     case \ReflectionMethod::class:
                                         /** @var \ReflectionMethod $arg */
                                         $arg = sprintf('<span class=type>ReflectionMethod</span>&lt;%s::%s>', $arg->getDeclaringClass()->getName(), $arg->getName());
                                         break;
                                     case \ReflectionFunction::class:
                                         /** @var \ReflectionFunction $arg */
                                         $arg = sprintf('<span class=type>ReflectionFunction</span>&lt;function at %s>', self::errorLink($arg->getFileName(), $arg->getStartLine(), 1, sprintf('%s line %d', basename($arg->getFileName()), $arg->getStartLine()), 'tag hint--rounded hint--top'));
                                         break;
                                     case \ReflectionParameter::class:
                                         /** @var \ReflectionParameter $arg */
                                         $arg = sprintf('<span class=type>ReflectionParameter</span>&lt;$%s>', $arg->getName());
                                         break;
                                     default:
                                         $arg = Debug::typeInfoOf($arg);
                                 }
                             } else {
                                 $arg = Debug::typeInfoOf($arg);
                             }
                     }
                     $args[] = $arg;
                 }
             }
             $args = implode(", ", $args);
             $args = "({$args})";
         } else {
             $args = '';
         }
         $file = isset($v['file']) ? $v['file'] : '';
         $fitems = explode(DIRECTORY_SEPARATOR, $file);
         $fname = '<span class="file">' . end($fitems) . '</span>';
         $line = isset($v['line']) ? $v['line'] : '&nbsp;';
         $lineStr = $line ? "<span class='line'>{$line}</span>" : '';
         $edit = $file ? self::errorLink($file, $line, 1, 'edit', '__btn') : '';
         $at = $file ? self::errorLink($file, $line, 1) : '&lt;unknown location&gt;';
         ErrorConsoleRenderer::renderStackFrame($count - $k, $fname, $lineStr, $fn, $args, $at, $edit);
     }
     return ob_get_clean();
 }
 private function unwind($e)
 {
     $this->routingLogger->writef("<#row>%sUnwinding the stack...</#row>", self::$unwinding ? '' : '<span class=__alert>' . Debug::getType($e) . '</span> ');
     self::$unwinding = true;
     throw $e;
 }
 /**
  * @param \Error|\Exception $e
  * @param Expression        $exp
  * @throws ComponentException
  */
 private function evalError($e, Expression $exp)
 {
     throw new ComponentException($this, Debug::grid(['Expression' => Debug::RAW_TEXT . "<kbd>{$exp}</kbd>", 'Compiled' => sprintf('%s<code>%s</code>', Debug::RAW_TEXT, \PhpCode::highlight("{$exp->translated}")), 'Error' => sprintf('%s%s %s', Debug::RAW_TEXT, Debug::typeInfoOf($e), $e->getMessage()), 'At' => sprintf('%s%s, line <b>%s</b>', Debug::RAW_TEXT, ErrorConsole::errorLink($e->getFile(), $e->getLine()), $e->getLine())], 'Error while evaluating data-binding expression'));
 }
 /**
  * Returns a formatted properties table.
  *
  * @param array $props
  * @return string
  */
 private static function properties(array $props)
 {
     return "<h6>Assigned properties</h6><table class=grid>\n" . str_replace(["'", '...'], ["<i>'</i>", '<i>...</i>'], implode('', map($props, function ($v, $k) {
         return "<tr><th>{$k}<td>" . (is_string($v) ? "'" . htmlspecialchars(trimText($v, 300, '...')) . "'" : Debug::toString($v));
     })), $o) . "\n</table>";
 }
 /**
  * Invokes a request handler.
  *
  * <p>The router does not call handlers directly; instead, it does it trough this method, so that calls can be
  * intercepted, validated and logged.
  *
  * > This method also functions as a router extension point.
  *
  * @param callable               $handler
  * @param ServerRequestInterface $request
  * @param ResponseInterface      $response
  * @param callable               $next
  * @return ResponseInterface
  */
 protected function callHandler(callable $handler, ServerRequestInterface $request, ResponseInterface $response, callable $next)
 {
     $this->currentRequestMutator->set($request);
     if ($handler instanceof RenderableInterface) {
         $class = $handler->getContextClass();
         $handler->setContext($this->injector->make($class));
     }
     /*try {
         $response = $handler ($request, $response, $next);
       }
       catch (HttpException $error) {
         // Convert HTTP exceptions to normal responses
         $msg = $error->getTitle () ?: str_segmentsFirst ($error->getMessage (), "\n"); // use only the first line of text
         return $response->withStatus ($error->getCode (), $msg);
       }*/
     $response = $handler($request, $response, $next);
     if (!$response) {
         throw new \RuntimeException(sprintf("Request handler <span class=__type>%s</span> did not return a response.", Debug::getType($handler)));
     }
     if (!$response instanceof ResponseInterface) {
         throw new \RuntimeException(sprintf("Response from request handler <span class=__type>%s</span> is not a <span class=type>ResponseInterface</span> implementation.", Debug::getType($handler)));
     }
     return $response;
 }
 protected function afterRender()
 {
     parent::afterRender();
     //----------------------------------------------------------------------------------------
     // View Model panel
     // (MUST run before the DOM panel to capture the data-binding stack at its current state)
     //----------------------------------------------------------------------------------------
     DebugConsole::registerPanel('view', new ConsoleLogger('View', 'fa fa-eye'));
     $VMFilter = function ($k, $v, $o) {
         if ($v instanceof DocumentContext || $v instanceof Component || $k === 'parent' || $k === 'model') {
             return '...';
         }
         return true;
     };
     $expMap = Expression::$inspectionMap;
     ksort($expMap);
     DebugConsole::logger('view')->withFilter($VMFilter, $this->context)->write('<#section|Compiled expressions>')->inspect($expMap)->write('</#section>');
     //------------
     // Model panel
     //------------
     DebugConsole::registerPanel('model', new ConsoleLogger('Model', 'fa fa-table'));
     $shadowDOM = $this->getShadowDOM();
     if ($shadowDOM) {
         $VMFilter = function ($k, $v, $o) {
             if ($v instanceof KernelSettings || $v instanceof NavigationInterface || $v instanceof NavigationLinkInterface || $v instanceof SessionInterface || $v instanceof ServerRequestInterface || $v instanceof DocumentContext || $v instanceof Component) {
                 return '...';
             }
             return true;
         };
         $binder = $shadowDOM->getDataBinder();
         DebugConsole::logger('model')->write('<#i>PAGE DATA BINDER: ' . Debug::getType($binder) . "</#i>")->write("<#section|PAGE VIEW MODEL>")->withFilter($VMFilter, $binder->getViewModel())->write("</#section>");
     }
     //-----------
     // DOM panel
     //-----------
     if ($this->matisseSettings->inspectDOM()) {
         DebugConsole::registerPanel('DOM', new ConsoleLogger('Server-side DOM', 'fa fa-sitemap'));
         $insp = $this->inspect(true);
         DebugConsole::logger('DOM')->write($insp);
     }
 }