private static function createShortcodeRegexContent(SyntaxInterface $syntax) { $open = self::quote($syntax->getOpeningTag()); $slash = self::quote($syntax->getClosingTagMarker()); $close = self::quote($syntax->getClosingTag()); $equals = self::quote($syntax->getParameterValueSeparator()); $string = self::quote($syntax->getParameterValueDelimiter()); $space = '\\s*'; // lookahead test for space, closing tag, self-closing tag or end of string $empty = '(?=\\s|' . $close . '|' . $slash . $space . $close . '|$)'; // equals sign and alphanumeric value $simple = $space . $equals . $space . '(?!=(?:\\s*|' . $close . '|' . $slash . $close . '))'; // equals sign and value without unescaped string delimiters enclosed in them $complex = $space . $equals . $space . $string . '(?:[^' . $string . '\\\\]*(?:\\\\.[^' . $string . '\\\\]*)*)' . $string; // complete parameters matching regex $parameters = '((?:\\s*(?:\\w+(?:' . $complex . '|' . $simple . '|' . $empty . ')))*)'; // alphanumeric characters and dash $name = '([\\w-]+)'; // non-greedy match for any characters $content = '(.*?)'; // equal beginning for each variant: open tag, name and parameters $common = $open . $space . $name . $parameters . $space; // closing tag variants: just closing tag, self closing tag or content // and closing block with backreference name validation $justClosed = $close; $selfClosed = '([' . $slash . '])' . $space . $close; $withContent = $close . $content . $open . $space . $slash . $space . '(\\2)' . $space . $close; return '(?:' . $common . '(?:' . $withContent . '|' . $justClosed . '|' . $selfClosed . '))'; }
private static function createShortcodeRegexContent(SyntaxInterface $syntax) { $open = self::quote($syntax->getOpeningTag()); $slash = self::quote($syntax->getClosingTagMarker()); $close = self::quote($syntax->getClosingTag()); $equals = self::quote($syntax->getParameterValueSeparator()); $string = self::quote($syntax->getParameterValueDelimiter()); $space = '\\s*'; // parameter and value separator can have any number of spaces around itself $equalsSpaced = $space . $equals . $space; // lookahead test for space, closing tag, self-closing tag or end of string $empty = '(?=\\s|' . $close . '|' . $slash . $space . $close . '|$)'; // equals sign and alphanumeric value $simple = '(?!=(?:\\s*|' . $close . '|' . $slash . $close . '))'; // equals sign and value without unescaped string delimiters enclosed in them $complex = $string . '(?:[^' . $string . '\\\\]*(?:\\\\.[^' . $string . '\\\\]*)*)' . $string; // complete parameters matching regex $parameters = '(?<parameters>(?:\\s*(?:\\w+(?:' . $equalsSpaced . $complex . '|' . $equalsSpaced . $simple . '|' . $empty . ')))*)'; // BBCode is the part after name that makes it behave like a non-empty parameter value $bbCode = '(?:' . $equals . $space . '(?<bbCode>' . $complex . '|' . $simple . '))?'; // alphanumeric characters and dash $name = '(?<name>' . static::buildNameRegex() . ')'; // non-greedy match for any characters $content = '(?<content>.*?)'; // equal beginning for each variant: open tag, name and parameters $common = $open . $space . $name . $space . $bbCode . $space . $parameters . $space; // closing tag variants: just closing tag, self closing tag or content // and closing block with backreference name validation $justClosed = $close; $selfClosed = '(?<marker>' . $slash . ')' . $space . $close; $withContent = $close . $content . $open . $space . '(?<markerContent>' . $slash . ')' . $space . '(\\k<name>)' . $space . $close; return '(?:' . $common . '(?:' . $withContent . '|' . $justClosed . '|' . $selfClosed . '))'; }
/** * @dataProvider provideSyntaxes */ public function testSyntax(SyntaxInterface $syntax, $open, $close, $slash, $parameter, $value) { $this->assertSame($open, $syntax->getOpeningTag()); $this->assertSame($close, $syntax->getClosingTag()); $this->assertSame($slash, $syntax->getClosingTagMarker()); $this->assertSame($parameter, $syntax->getParameterValueSeparator()); $this->assertSame($value, $syntax->getParameterValueDelimiter()); }
private function getTokenizerRegex(SyntaxInterface $syntax) { $quote = function ($text, $group) { return '(?<' . $group . '>' . preg_replace('/(.)/us', '\\\\$0', $text) . ')'; }; $rules = array($quote($syntax->getOpeningTag(), 'open'), $quote($syntax->getClosingTag(), 'close'), $quote($syntax->getClosingTagMarker(), 'marker'), $quote($syntax->getParameterValueSeparator(), 'separator'), $quote($syntax->getParameterValueDelimiter(), 'delimiter'), '(?<ws>\\s+)', '(?<string>[\\w-]+|\\\\.|.)'); return '~(' . implode('|', $rules) . ')~us'; }
private function isDelimitedValue($value) { return preg_match('/^' . $this->syntax->getParameterValueDelimiter() . '/us', $value) && preg_match('/' . $this->syntax->getParameterValueDelimiter() . '$/us', $value); }