Returns PHTML from pug node input.

@param NodeInterface    $node   input
@param ElementInterface $parent optional parent element

@throws CompilerException

@return ElementInterface
185810
public function compileNode(NodeInterface $node, ElementInterface $parent = null)
    {
        $nodeEvent = new NodeEvent($node);
        $this->trigger($nodeEvent);
        $node = $nodeEvent->getNode();

        $this->currentNode = $node;

        foreach ($this->nodeCompilers as $className => $compiler) {
            if (is_a($node, $className)) {
                if (!($compiler instanceof NodeCompilerInterface)) {
                    $compiler = $this->getNamedCompiler($compiler);
                }

                $element = $compiler->compileNode($node, $parent);

                if ($element instanceof ElementInterface && !($element instanceof BlockElement)) {
                    $elementEvent = new ElementEvent($nodeEvent, $element);
                    $this->trigger($elementEvent);
                    $element = $elementEvent->getElement();
                }

                return $element;
            }
        }

        $this->throwException(
            'No compiler found able to compile '.get_class($node),
            $node
        );
    }
1300671
protected function renderNodePropertyAttribute(NodeInterface $node, $propertyName)
    {
        $attributes = [];
        /** @var $contentContext ContentContext */
        $contentContext = $node->getContext();
        // skip the node name of the site node - TODO: Why do we need this?
        if ($propertyName === '_name' && $node === $contentContext->getCurrentSiteNode()) {
            return $attributes;
        }

        $dataType = $node->getNodeType()->getPropertyType($propertyName);
        $dasherizedPropertyName = $this->dasherize($propertyName);

        $propertyValue = $this->nodePropertyConverterService->getProperty($node, $propertyName);
        $propertyValue = $propertyValue === null ? '' : $propertyValue;
        $propertyValue = !is_string($propertyValue) ? json_encode($propertyValue) : $propertyValue;

        if ($dataType !== 'string') {
            $attributes['data-nodedatatype-' . $dasherizedPropertyName] = 'xsd:' . $dataType;
        }

        $attributes['data-node-' . $dasherizedPropertyName] = $propertyValue;

        return $attributes;
    }
831004
public function createChildNodes(NodeInterface $node)
    {
        $nodeType = $node->getNodeType();
        foreach ($nodeType->getAutoCreatedChildNodes() as $childNodeName => $childNodeType) {
            try {
                $node->createNode($childNodeName, $childNodeType);
            } catch (NodeExistsException $exception) {
                // If you have a node that has been marked as removed, but is needed again
                // the old node is recovered
                $childNodePath = NodePaths::addNodePathSegment($node->getPath(), $childNodeName);
                $contextProperties = $node->getContext()->getProperties();
                $contextProperties['removedContentShown'] = true;
                $context = $this->contextFactory->create($contextProperties);
                $childNode = $context->getNode($childNodePath);
                if ($childNode->isRemoved()) {
                    $childNode->setRemoved(false);
                }
            }
        }
    }
535509
public function invoke($node, NodeInterface $parent): void
    {
        if (! $node instanceof Node\Stmt\Class_ || ! $parent instanceof PhpFileModelInterface) {
            throw new Exception('ClassNodeParser is made to parse a class node');
        }
        $class = new ClassModel();
        $class->setParentNode($parent);
        $class->setName(ClassLikeNameHelper::getName($node));
        $class->setIsAbstract($node->isAbstract());
        $class->setIsFinal($node->isFinal());
        $parent->addConcreteUse($parent->getFullNameFor($class->getName()), $class->getName());

        if (($documentation = $node->getDocComment()) !== null) {
            $this->documentationNodeParser->invoke($documentation, $class);
        }

        $this->parseSubNodes($node->stmts, $class);

        $parent->addClass($class);
    }
833540
public function addNode(NodeInterface $node)
    {
        if ($this->checkChildNode($node)) {
            $this->nodes->add($node);

            $node->setPosition(count($this->getNodes()));
            $node->setParent($this);
        }

        return $this;
    }
22494
public function serializeNodeRecursively(NodeInterface $node, ControllerContext $controllerContext)
    {
        $result = [
            $node->getContextPath() => $this->nodeInfoHelper->renderNodeWithPropertiesAndChildrenInformation($node, $controllerContext)
        ];

        if ($this->isRecursive === true) {
            foreach ($node->getChildNodes() as $childNode) {
                $result = array_merge($result, $this->serializeNodeRecursively($childNode, $controllerContext));
            }
        }

        return $result;
    }
732847
public function getNodeCampaignNode(NodeInterface $node) {
    $campaign = NULL;

    if ($node->getType() == 'campaign') {
      return $node;
    }

    if ($node->getType() == 'campaign_page') {
      $campaign = $node->field_campaign_parent->entity;
      if (!empty($campaign)) {
        return $campaign;
      }
    }

    /** @var \Drupal\node\NodeStorage $nodeStorage */
    $nodeStorage = $this->entityTypeManager->getStorage('node');

    // Get Campaign node with reference to given Landing page node.
    /** @var \Drupal\Core\Entity\Query\QueryInterface $query */
    $query = $nodeStorage->getQuery()
      ->condition('status', 1)
      ->condition('type', 'campaign');
    $orGroup = $query->orConditionGroup()
      ->condition('field_campaign_pages', $node->id(), 'IN')
      ->condition('field_pause_landing_page', $node->id());
    $nids = $query->condition($orGroup)->execute();

    /** @var \Drupal\node\NodeInterface $campaign */
    $campaign = $nodeStorage->load(reset($nids));

    return $campaign;
  }
888557
public function parseElement(Node $parent, \DOMElement $element)
    {
        if (AtomPub::NS === $element->namespaceURI) {
            switch ($element->localName) {
                case 'collection':
                    // Node name already checked
                    return new Collection($parent, $element);
                case 'workspace':
                    // Node name already checked
                    return new Workspace($parent, $element);
            }
        }

        return null;
    }
42477
protected function getParentElementId(DOMNode $node)
	{
		$parentNode = $node->parentNode;
		while (isset($parentNode))
		{
			if ($parentNode->nodeName === 'element')
			{
				return $parentNode->getAttribute('id');
			}
			$parentNode = $parentNode->parentNode;
		}
	}
1180949
protected function processDeclaration($node, $parent) {
        $rules = [];

        foreach ($node->getRules() as $key => $rule) {
            $name = $rule->getRule();
            $seen[$name] = true;

            if (!isset(self::$rules[$name])) {
                $rules[] = $rule;
                continue;
            }

            foreach (self::$rules[$name] as $prefix) {
                $newname = $prefix . $name;
                if (isset($seen[$newname])) {
                    continue;
                }
                $newrule = clone $rule;
                $newrule->setRule($newname);
                $rules[] = $newrule;
            }

            $rules[] = $rule;
        }

        $node->setRules($this->manipulateRuleValues($rules));

        if ($node instanceof DeclarationBlock) {
            $selectors = $node->getSelectors();
            foreach ($selectors as $key => $selector) {

                $matches = [];
                if (preg_match($this->pseudosregex, $selector->getSelector(), $matches)) {

                    $newnode = clone $node;
                    foreach (self::$pseudos[$matches[1]] as $newpseudo) {
                        $newselector = new Selector(str_replace($matches[1], $newpseudo, $selector->getSelector()));
                        $selectors[$key] = $newselector;
                        $newnode = clone $node;
                        $newnode->setSelectors($selectors);
                        $parent->insert($newnode, $node);
                    }

                    // We're only expecting one affected pseudo class per block.
                    break;
                }
            }
        }
    }
672114
public function generateCss(NodeInterface $node)
    {
        $css = '';

        foreach (self::PROPERTY_MAPPING as $key => $cssProperty) {
            // Get value, also check for `0` values using strlen()
            if (($value = $node->getProperty($key)) || strlen($value)) {
                // if numeric value is provided, add default unit (e.g. px)
                // but don't add it to zero values
                if ($value && is_numeric($value)) {
                    $value .= self::DEFAULT_UNIT;
                }

                $css .= "$cssProperty:$value;";
            }
        }

        return $css;
    }
1358477
public function invoke($node, NodeInterface $parent): void
    {
        if (! $parent instanceof TypeInterface) {
            throw new Exception('TypeNodeParser is made to parse a type node');
        }

        // If it is a nullable type
        if ($node instanceof Node\NullableType) {
            $parent->setNullable(true);

            $this->invoke($node->type, $parent);
            return;
        }
        // Handle scalar type in identifier
        if ($node instanceof Node\Identifier
            && Validator::contains($node->name)->validate(TypeInterface::RESERVED_TYPE_IDENTIFIERS)
        ) {
            $node = $node->name;
        }
        // If it is a class like type
        if ($node instanceof Node\Name || $node instanceof Node\Identifier) {
            $parent->setType(TypeInterface::CUSTOM);
            $parent->setCustomType($this->getClassType($node, $parent));
            return;
        }
        // If it is a scalar type
        if (Validator::stringType()->validate($node)) {
            $parent->setType(constant(TypeInterface::class . '::' . strtoupper($node)));
            return;
        }

        throw new Exception('TypeNodeParser is made to parse a type node');
    }
736587
private function renderNode(NodeInterface $node, int $node_id): string
    {
        if ($node instanceof LeafNode) {
            return $this->renderLeafNode($node, $node_id);
        } elseif ($node instanceof RootNode) {
            return $this->renderRootNode($node_id);
        }
        return $this->renderInternalNode($node, $node_id);
    }
1262987
protected function compileElement(Node $node)
    {

        $phtml = '';

        $tag = $this->interpolate($node->tag ?: $this->options['default_tag']);

        $phtml .= "<{$tag}";

        $htmlMode = $this->isHtml();
        $xhtmlMode = $this->isXhtml();
        $xmlMode = $this->isXml();
        $anyHtmlMode = $htmlMode || $xhtmlMode;
        $anyXmlMode = $xmlMode || $xhtmlMode;

        $forceInline = $anyHtmlMode && in_array($tag, $this->options['force_inlined_tags']);

        if ($forceInline) {

            $this->forceInline = true;
        }

        $nodeAttributes = $node->attributes;

        //In the following lines we kind of map assignments
        //to attributes (that's the core of how cross-assignments work)
        //&href('a', 'b', 'c') will add 3 attributes href=a, href=b and href=b
        //to the attributes we work on
        //This is not the final way on how attributes should work, but at least it has some (somewhat) useful
        //functionality.
        foreach ($node->assignments as $assignment) {

            $name = $assignment->name;

            //This line provides compatibility to the offical jade method
            if ($anyHtmlMode && $name === 'classes')
                $name = 'class';

            if ($anyHtmlMode && $name === 'styles')
                $name = 'style';

            if ($anyHtmlMode && $name === 'attributes') {

                foreach ($assignment->attributes as $attr) {

                    if ($attr->name) {

                        $nodeAttributes[] = $attr;
                        continue;
                    }

                    //TODO: implement cross-assigning attributes
                    //e.g. &attributes(['class' => 'abc', 'style' => ['width' => '100%']])
                    $this->throwException(
                        "Cross-assigning an array of attributes"
                        ." is not supported right now, but we're working"
                        ." on it!",
                        $node
                    );
                }
                continue;
            }

            foreach ($assignment->attributes as $attr) {

                if (!$attr->value)
                    $attr->value = $attr->name;

                $attr->name = $name;
                $nodeAttributes[] = $attr;
            }
        }

        if (count($nodeAttributes) > 0) {

            //Iterate all attributes.
            //Multiple attributes with the same name
            //will be put together in an array
            //and passed to the respective builder method
            $attributes = [];
            foreach ($nodeAttributes as $attr) {

                if (isset($attributes[$attr->name]))
                    $attributes[$attr->name][] = $attr;
                else
                    $attributes[$attr->name] = [$attr];
            }

            //first iteration of sanitizing values
            foreach ($attributes as $name => $attrs) {

                $values = [];
                $escaped = true;
                foreach ($attrs as $attr) {

                    $value = trim($attr->value);

                    if ($value) {

                        if ($this->isVariable($value) && !$attr->unchecked) {

                            $values[] = 'isset(' . $value . ') ? ' . $value . ' : false';
                        } else {

                            $values[] = $value;
                        }
                    }

                    if (!$attr->escaped)
                        $escaped = false;
                }

                //In XML-mode, self-repeating attributes are automatically expanded
                if ($anyXmlMode || $xmlMode && count($values) < 1) {

                    if ($xhtmlMode && in_array($name, $this->options['self_repeating_attributes']))
                        $values[] = $name;
                    else
                        $values[] = '';
                }

                $quot = $this->options['quote_style'];
                $builder = '\\Tale\\Jade\\Compiler\\build_value';

                //Handle specific attribute styles for HTML
                if ($anyHtmlMode) {

                    switch ($name) {
                        case 'class':
                            $builder = '\\Tale\\Jade\\Compiler\\build_class_value';
                            break;
                        case 'style':
                            $builder = '\\Tale\\Jade\\Compiler\\build_style_value';
                            break;
                    }

                    if (strncmp($name, 'data-', 5) === 0)
                        $builder = '\\Tale\\Jade\\Compiler\\build_data_value';
                }

                $escaped = $escaped ? 'true' : 'false';

                $pair = '';
                if (count($values) < 1) {

                    $pair = " $name";
                } else if (count(array_filter($values, [$this, 'isScalar'])) === count($values)) {

                    //We got all scalar values, we can evaluate them directly, so no code needed in the PHTML output
                    $pair = " $name=";
                    $values = array_map(function ($val) {

                        return $this->compileScalar($val);
                    }, $values);
                    $pair .= call_user_func($builder, count($values) === 1 ? $values[0] : $values, $quot, $escaped === 'true');
                } else {

                    //If there's any kind of expression in the attribute, we
                    //also check if something of the expression is false or null
                    //and if it is, we don't print the attribute

                    $values = array_map(function ($val) use ($quot, $builder, $escaped) {

                        return $this->isScalar($val)
                            ? call_user_func($builder, $this->compileScalar($val, true), $quot, $escaped === 'true')
                            : $val;
                    }, $values);

                    $quot = $quot === '\'' ? '\\\'' : $quot;
                    //We don't need to run big array stuff if there's only one value
                    if (count($values) === 1) {

                        $pair = $this->createCode(
                            '$__value = '.$values[0].'; '
                            .'if (!\\Tale\\Jade\\Compiler\\is_null_or_false($__value)) '
                            ."echo ' $name='.$builder(\$__value, '$quot', $escaped); "
                            .'unset($__value);'
                        );
                    } else {

                        $pair = $this->createCode(
                            '$__values = ['.implode(', ', $values).']; '
                            .'if (!\\Tale\\Jade\\Compiler\\is_array_null_or_false($__values)) '
                            ."echo ' $name='.$builder(\$__values, '$quot', $escaped); "
                            .'unset($__values);'
                        );
                    }
                }

                $phtml .= $pair;
            }
        }

        $hasChildren = count($node->children) > 0;
        $isSelfClosing = in_array($tag, $this->options['self_closing_tags']);

        if (!$hasChildren && (!$htmlMode || !$isSelfClosing)) {

            if ($anyHtmlMode && !$isSelfClosing) {

                //Force closed tag in HTML
                $phtml .= "></{$tag}>";

                return $phtml;
            }

            //Allow /> closing in all other modes
            $phtml .= ' />';

            return $phtml;
        } else
            $phtml .= '>';

        if (!$hasChildren)
            return $phtml;

        $phtml .= $this->compileChildren($node->children);
        $phtml .= $this->newLine().$this->indent()."</{$tag}>";

        if ($forceInline)
            $this->forceInline = false;

        return $phtml;
    }
205166
public function getNodeCampNode(NodeInterface $node) {
    $camp = NULL;
    switch ($node->bundle()) {
      case 'camp':
        $camp = $node;
        break;

      case 'landing_page':
        $camp = $this->getLandingPageCampNode($node);
        break;
    }

    return $camp;
  }
1085425
public function invoke($node, NodeInterface $parent): void
    {
        if (! $node instanceof Node\Stmt\Use_ || ! $parent instanceof PhpFileModelInterface) {
            throw new Exception('UseNodeParser is made to parse a use node');
        }

        if ($node->type === Node\Stmt\Use_::TYPE_NORMAL) {
            foreach ($node->uses as $use) {
                $parent->addUse($use->getAlias()->name, $use->name->toString());
            }
        }
    }
146328
public function invoke($node, NodeInterface $parent): void
    {
        if (! $node instanceof Node\Stmt\GroupUse || ! $parent instanceof PhpFileModelInterface) {
            throw new Exception('GroupUseNodeParser is made to parse a use group node');
        }

        if ($this->validateType($node->type)) {
            $prefix = $node->prefix->toString();
            foreach ($node->uses as $use) {
                if ($this->validateType($node->type)) {
                    $parent->addUse($use->getAlias()->name, $prefix . '\\' . $use->name->toString());
                }
            }
        }
    }