/** * @return array */ public static function exportRules(Rules $rules, $json = TRUE) { $payload = array(); foreach ($rules as $rule) { if (!is_string($op = $rule->validator)) { if (!Nette\Utils\Callback::isStatic($op)) { continue; } $op = Nette\Utils\Callback::toString($op); } if ($rule->branch) { $item = array('op' => ($rule->isNegative ? '~' : '') . $op, 'rules' => static::exportRules($rule->branch, FALSE), 'control' => $rule->control->getHtmlName()); if ($rule->branch->getToggles()) { $item['toggle'] = $rule->branch->getToggles(); } } else { $item = array('op' => ($rule->isNegative ? '~' : '') . $op, 'msg' => Validator::formatMessage($rule, FALSE)); } if (is_array($rule->arg)) { foreach ($rule->arg as $key => $value) { $item['arg'][$key] = $value instanceof IControl ? array('control' => $value->getHtmlName()) : $value; } } elseif ($rule->arg !== NULL) { $item['arg'] = $rule->arg instanceof IControl ? array('control' => $rule->arg->getHtmlName()) : $rule->arg; } $payload[] = $item; } return $json ? $payload ? Nette\Utils\Json::encode($payload) : NULL : $payload; }
/** * Formats PHP code for class instantiating, function calling or property setting in PHP. * @return string * @internal */ public function formatStatement(Statement $statement) { $entity = $this->normalizeEntity($statement->getEntity()); $arguments = $statement->arguments; if (is_string($entity) && Strings::contains($entity, '?')) { // PHP literal return $this->formatPhp($entity, $arguments); } elseif ($service = $this->getServiceName($entity)) { // factory calling $params = []; foreach ($this->definitions[$service]->parameters as $k => $v) { $params[] = preg_replace('#\\w+\\z#', '\\$$0', is_int($k) ? $v : $k) . (is_int($k) ? '' : ' = ' . PhpHelpers::dump($v)); } $rm = new \ReflectionFunction(create_function(implode(', ', $params), '')); $arguments = Helpers::autowireArguments($rm, $arguments, $this); return $this->formatPhp('$this->?(?*)', [Container::getMethodName($service), $arguments]); } elseif ($entity === 'not') { // operator return $this->formatPhp('!?', [$arguments[0]]); } elseif (is_string($entity)) { // class name if ($constructor = (new ReflectionClass($entity))->getConstructor()) { $this->addDependency((string) $constructor->getFileName()); $arguments = Helpers::autowireArguments($constructor, $arguments, $this); } elseif ($arguments) { throw new ServiceCreationException("Unable to pass arguments, class {$entity} has no constructor."); } return $this->formatPhp("new {$entity}" . ($arguments ? '(?*)' : ''), [$arguments]); } elseif (!Nette\Utils\Arrays::isList($entity) || count($entity) !== 2) { throw new ServiceCreationException(sprintf('Expected class, method or property, %s given.', PhpHelpers::dump($entity))); } elseif (!preg_match('#^\\$?' . PhpHelpers::PHP_IDENT . '\\z#', $entity[1])) { throw new ServiceCreationException("Expected function, method or property name, '{$entity['1']}' given."); } elseif ($entity[0] === '') { // globalFunc return $this->formatPhp("{$entity['1']}(?*)", [$arguments]); } elseif ($entity[0] instanceof Statement) { $inner = $this->formatPhp('?', [$entity[0]]); if (substr($inner, 0, 4) === 'new ') { $inner = "({$inner})"; } return $this->formatPhp("{$inner}->?(?*)", [$entity[1], $arguments]); } elseif (Strings::contains($entity[1], '$')) { // property setter Validators::assert($arguments, 'list:1', "setup arguments for '" . Nette\Utils\Callback::toString($entity) . "'"); if ($this->getServiceName($entity[0])) { return $this->formatPhp('?->? = ?', [$entity[0], substr($entity[1], 1), $arguments[0]]); } else { return $this->formatPhp($entity[0] . '::$? = ?', [substr($entity[1], 1), $arguments[0]]); } } elseif ($service = $this->getServiceName($entity[0])) { // service method $class = $this->definitions[$service]->getImplement(); if (!$class || !method_exists($class, $entity[1])) { $class = $this->definitions[$service]->getClass(); } if ($class) { $arguments = $this->autowireArguments($class, $entity[1], $arguments); } return $this->formatPhp('?->?(?*)', [$entity[0], $entity[1], $arguments]); } else { // static method $arguments = $this->autowireArguments($entity[0], $entity[1], $arguments); return $this->formatPhp("{$entity['0']}::{$entity['1']}(?*)", [$arguments]); } }
/** * @return array */ protected static function exportRules($rules) { $payload = array(); foreach ($rules as $rule) { if (!is_string($op = $rule->operation)) { if (!Nette\Utils\Callback::isStatic($op)) { continue; } $op = Nette\Utils\Callback::toString($op); } if ($rule->type === Rule::VALIDATOR) { $item = array('op' => ($rule->isNegative ? '~' : '') . $op, 'msg' => $rules->formatMessage($rule, FALSE)); } elseif ($rule->type === Rule::CONDITION) { $item = array('op' => ($rule->isNegative ? '~' : '') . $op, 'rules' => static::exportRules($rule->subRules), 'control' => $rule->control->getHtmlName()); if ($rule->subRules->getToggles()) { $item['toggle'] = $rule->subRules->getToggles(); } } if (is_array($rule->arg)) { foreach ($rule->arg as $key => $value) { $item['arg'][$key] = $value instanceof IControl ? array('control' => $value->getHtmlName()) : $value; } } elseif ($rule->arg !== NULL) { $item['arg'] = $rule->arg instanceof IControl ? array('control' => $rule->arg->getHtmlName()) : $rule->arg; } $payload[] = $item; } return $payload; }
/** * @return array */ public static function exportRules(Rules $rules) { $payload = []; foreach ($rules as $rule) { if (!is_string($op = $rule->validator)) { if (!Nette\Utils\Callback::isStatic($op)) { continue; } $op = Nette\Utils\Callback::toString($op); } if ($rule->branch) { $item = ['op' => ($rule->isNegative ? '~' : '') . $op, 'rules' => static::exportRules($rule->branch), 'control' => $rule->control->getHtmlName()]; if ($rule->branch->getToggles()) { $item['toggle'] = $rule->branch->getToggles(); } elseif (!$item['rules']) { continue; } } else { $item = ['op' => ($rule->isNegative ? '~' : '') . $op, 'msg' => Validator::formatMessage($rule, FALSE)]; } if (is_array($rule->arg)) { $item['arg'] = []; foreach ($rule->arg as $key => $value) { $item['arg'][$key] = $value instanceof IControl ? ['control' => $value->getHtmlName()] : $value; } } elseif ($rule->arg !== NULL) { $item['arg'] = $rule->arg instanceof IControl ? ['control' => $rule->arg->getHtmlName()] : $rule->arg; } $payload[] = $item; } if ($payload && $rules->isOptional()) { array_unshift($payload, ['op' => 'optional']); } return $payload; }
/** * Registers callback as template compile-time filter. * @param callable * @return self */ public function registerFilter($callback) { if ($callback instanceof Latte\Engine) { // back compatibility $this->latte = $callback; } elseif (is_array($callback) && $callback[0] instanceof Latte\Engine) { $this->latte = $callback[0]; } elseif (strpos(Callback::toString($callback), 'Latte\\Engine') !== FALSE) { $this->latte = TRUE; } elseif ($this->latte) { throw new Nette\DeprecatedException('Adding filters after Latte is not possible.'); } else { $this->filters[] = Callback::check($callback); } return $this; }
private function renderListeners($ids) { static $addIcon; if (empty($addIcon)) { $addIcon = '<img width="18" height="18" src="data:image/png;base64,' . base64_encode(file_get_contents(__DIR__ . '/add.png')) . '" title="Listener" />'; } $registeredClasses = $this->getClassMap(); $h = 'htmlspecialchars'; $shortFilename = function (Nette\Reflection\GlobalFunction $refl) { $title = '.../' . basename($refl->getFileName()) . ':' . $refl->getStartLine(); if ($editor = Tracy\Helpers::editorUri($refl->getFileName(), $refl->getStartLine())) { return sprintf(' defined at <a href="%s">%s</a>', htmlspecialchars($editor), $title); } return ' defined at ' . $title; }; $s = ''; foreach ($ids as $id) { if (is_callable($id)) { $s .= '<tr><td width=18>' . $addIcon . '</td><td><pre class="nette-dump"><span class="nette-dump-object">' . Callback::toString($id) . ($id instanceof \Closure ? $shortFilename(Callback::toReflection($id)) : '') . '</span></span></th></tr>'; continue; } if (!$this->sl->isCreated($id) && ($class = array_search($id, $registeredClasses, TRUE))) { $s .= '<tr><td width=18>' . $addIcon . '</td><td><pre class="nette-dump"><span class="nette-dump-object">' . $h(Nette\Reflection\ClassType::from($class)->getName()) . '</span></span></th></tr>'; } else { try { $s .= '<tr><td width=18>' . $addIcon . '</td><td>' . self::dumpToHtml($this->sl->getService($id)) . '</th></tr>'; } catch (\Exception $e) { $s .= "<tr><td colspan=2>Service {$id} cannot be loaded because of exception<br><br>\n" . (string) $e . '</td></th>'; } } } return $s; }
/** * Formats PHP code for class instantiating, function calling or property setting in PHP. * @return string * @internal */ public function formatStatement(Statement $statement) { $entity = $this->normalizeEntity($statement->entity); $arguments = $statement->arguments; if (is_string($entity) && Strings::contains($entity, '?')) { // PHP literal return $this->formatPhp($entity, $arguments); } elseif ($service = $this->getServiceName($entity)) { // factory calling $params = array(); foreach ($this->definitions[$service]->parameters as $k => $v) { $params[] = preg_replace('#\w+\z#', '\$$0', (is_int($k) ? $v : $k)) . (is_int($k) ? '' : ' = ' . PhpHelpers::dump($v)); } $rm = new Reflection\GlobalFunction(create_function(implode(', ', $params), '')); $arguments = Helpers::autowireArguments($rm, $arguments, $this); return $this->formatPhp('$this->?(?*)', array(Container::getMethodName($service), $arguments)); } elseif ($entity === 'not') { // operator return $this->formatPhp('!?', array($arguments[0])); } elseif (is_string($entity)) { // class name if ($constructor = Reflection\ClassType::from($entity)->getConstructor()) { $this->addDependency($constructor->getFileName()); $arguments = Helpers::autowireArguments($constructor, $arguments, $this); } elseif ($arguments) { throw new ServiceCreationException("Unable to pass arguments, class $entity has no constructor."); } return $this->formatPhp("new $entity" . ($arguments ? '(?*)' : ''), array($arguments)); } elseif (!Nette\Utils\Arrays::isList($entity) || count($entity) !== 2) { throw new ServiceCreationException(sprintf('Expected class, method or property, %s given.', PhpHelpers::dump($entity))); } elseif ($entity[0] === '') { // globalFunc return $this->formatPhp("$entity[1](?*)", array($arguments)); } elseif (Strings::contains($entity[1], '$')) { // property setter Validators::assert($arguments, 'list:1', "setup arguments for '" . Nette\Utils\Callback::toString($entity) . "'"); if ($this->getServiceName($entity[0])) { return $this->formatPhp('?->? = ?', array($entity[0], substr($entity[1], 1), $arguments[0])); } else { return $this->formatPhp($entity[0] . '::$? = ?', array(substr($entity[1], 1), $arguments[0])); } } elseif ($service = $this->getServiceName($entity[0])) { // service method $class = $this->definitions[$service]->implement; if (!$class || !method_exists($class, $entity[1])) { $class = $this->definitions[$service]->class; } if ($class) { $arguments = $this->autowireArguments($class, $entity[1], $arguments); } return $this->formatPhp('?->?(?*)', array($entity[0], $entity[1], $arguments)); } else { // static method $arguments = $this->autowireArguments($entity[0], $entity[1], $arguments); return $this->formatPhp("$entity[0]::$entity[1](?*)", array($arguments)); } }
/** * @return Statement */ public function completeStatement(Statement $statement) { $entity = $this->normalizeEntity($statement->getEntity()); $arguments = $statement->arguments; if (is_string($entity) && Strings::contains($entity, '?')) { // PHP literal } elseif ($service = $this->getServiceName($entity)) { // factory calling $params = []; foreach ($this->definitions[$service]->parameters as $k => $v) { $params[] = preg_replace('#\\w+\\z#', '\\$$0', is_int($k) ? $v : $k) . (is_int($k) ? '' : ' = ' . PhpHelpers::dump($v)); } $rm = new \ReflectionFunction(create_function(implode(', ', $params), '')); $arguments = Helpers::autowireArguments($rm, $arguments, $this); $entity = '@' . $service; } elseif ($entity === 'not') { // operator } elseif (is_string($entity)) { // class name if (!class_exists($entity)) { throw new ServiceCreationException("Class {$entity} not found."); } elseif ((new ReflectionClass($entity))->isAbstract()) { throw new ServiceCreationException("Class {$entity} is abstract."); } elseif (($rm = (new ReflectionClass($entity))->getConstructor()) !== NULL && !$rm->isPublic()) { $visibility = $rm->isProtected() ? 'protected' : 'private'; throw new ServiceCreationException("Class {$entity} has {$visibility} constructor."); } elseif ($constructor = (new ReflectionClass($entity))->getConstructor()) { $this->addDependency($constructor); $arguments = Helpers::autowireArguments($constructor, $arguments, $this); } elseif ($arguments) { throw new ServiceCreationException("Unable to pass arguments, class {$entity} has no constructor."); } } elseif (!Nette\Utils\Arrays::isList($entity) || count($entity) !== 2) { throw new ServiceCreationException(sprintf('Expected class, method or property, %s given.', PhpHelpers::dump($entity))); } elseif (!preg_match('#^\\$?' . PhpHelpers::PHP_IDENT . '(\\[\\])?\\z#', $entity[1])) { throw new ServiceCreationException("Expected function, method or property name, '{$entity['1']}' given."); } elseif ($entity[0] === '') { // globalFunc if (!Nette\Utils\Arrays::isList($arguments)) { throw new ServiceCreationException("Unable to pass specified arguments to {$entity['0']}."); } elseif (!function_exists($entity[1])) { throw new ServiceCreationException("Function {$entity['1']} doesn't exist."); } $rf = new \ReflectionFunction($entity[1]); $this->addDependency($rf); $arguments = Helpers::autowireArguments($rf, $arguments, $this); } else { if ($entity[0] instanceof Statement) { $entity[0] = $this->completeStatement($entity[0]); } elseif ($service = $this->getServiceName($entity[0])) { // service method $entity[0] = '@' . $service; } if ($entity[1][0] === '$') { // property getter, setter or appender Validators::assert($arguments, 'list:0..1', "setup arguments for '" . Nette\Utils\Callback::toString($entity) . "'"); if (!$arguments && substr($entity[1], -2) === '[]') { throw new ServiceCreationException("Missing argument for {$entity['1']}."); } } elseif ($class = empty($service) || $entity[1] === 'create' ? $this->resolveEntityClass($entity[0]) : $this->definitions[$service]->getClass()) { $arguments = $this->autowireArguments($class, $entity[1], $arguments); } } array_walk_recursive($arguments, function (&$val) { if ($val instanceof Statement) { $val = $this->completeStatement($val); } elseif ($val === $this) { trigger_error("Replace object ContainerBuilder in Statement arguments with '@container'.", E_USER_DEPRECATED); $val = self::literal('$this'); } elseif ($val instanceof ServiceDefinition) { $val = '@' . current(array_keys($this->getDefinitions(), $val, TRUE)); } elseif (is_string($val) && strlen($val) > 1 && $val[0] === '@' && $val[1] !== '@') { $pair = explode('::', $val, 2); $name = $this->getServiceName($pair[0]); if (!isset($pair[1])) { // @service $val = '@' . $name; } elseif (preg_match('#^[A-Z][A-Z0-9_]*\\z#', $pair[1], $m)) { // @service::CONSTANT $val = self::literal($this->getDefinition($name)->getClass() . '::' . $pair[1]); } else { // @service::property $val = new Statement(['@' . $name, '$' . $pair[1]]); } } }); return new Statement($entity, $arguments); }