ÿØÿà JFIF    ÿÛ „ ( %!1!%*+...983,7(-.- PK]6H Yaml/Unescaper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; /** * Unescaper encapsulates unescaping rules for single and double-quoted * YAML strings. * * @author Matthew Lewinski */ class Unescaper { // Parser and Inline assume UTF-8 encoding, so escaped Unicode characters // must be converted to that encoding. const ENCODING = 'UTF-8'; // Regex fragment that matches an escaped character in a double quoted // string. const REGEX_ESCAPED_CHARACTER = "\\\\([0abt\tnvfre \\\"\\/\\\\N_LP]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})"; /** * Unescapes a single quoted string. * * @param string $value A single quoted string. * * @return string The unescaped string. */ public function unescapeSingleQuotedString($value) { return str_replace('\'\'', '\'', $value); } /** * Unescapes a double quoted string. * * @param string $value A double quoted string. * * @return string The unescaped string. */ public function unescapeDoubleQuotedString($value) { $self = $this; $callback = function ($match) use ($self) { return $self->unescapeCharacter($match[0]); }; // evaluate the string return preg_replace_callback('/'.self::REGEX_ESCAPED_CHARACTER.'/u', $callback, $value); } /** * Unescapes a character that was found in a double-quoted string * * @param string $value An escaped character * * @return string The unescaped character */ public function unescapeCharacter($value) { switch ($value{1}) { case '0': return "\x0"; case 'a': return "\x7"; case 'b': return "\x8"; case 't': return "\t"; case "\t": return "\t"; case 'n': return "\n"; case 'v': return "\xb"; case 'f': return "\xc"; case 'r': return "\xd"; case 'e': return "\x1b"; case ' ': return ' '; case '"': return '"'; case '/': return '/'; case '\\': return '\\'; case 'N': // U+0085 NEXT LINE return $this->convertEncoding("\x00\x85", self::ENCODING, 'UCS-2BE'); case '_': // U+00A0 NO-BREAK SPACE return $this->convertEncoding("\x00\xA0", self::ENCODING, 'UCS-2BE'); case 'L': // U+2028 LINE SEPARATOR return $this->convertEncoding("\x20\x28", self::ENCODING, 'UCS-2BE'); case 'P': // U+2029 PARAGRAPH SEPARATOR return $this->convertEncoding("\x20\x29", self::ENCODING, 'UCS-2BE'); case 'x': $char = pack('n', hexdec(substr($value, 2, 2))); return $this->convertEncoding($char, self::ENCODING, 'UCS-2BE'); case 'u': $char = pack('n', hexdec(substr($value, 2, 4))); return $this->convertEncoding($char, self::ENCODING, 'UCS-2BE'); case 'U': $char = pack('N', hexdec(substr($value, 2, 8))); return $this->convertEncoding($char, self::ENCODING, 'UCS-4BE'); } } /** * Convert a string from one encoding to another. * * @param string $value The string to convert * @param string $to The input encoding * @param string $from The output encoding * * @return string The string with the new encoding * * @throws \RuntimeException if no suitable encoding function is found (iconv or mbstring) */ private function convertEncoding($value, $to, $from) { if (function_exists('mb_convert_encoding')) { return mb_convert_encoding($value, $to, $from); } elseif (function_exists('iconv')) { return iconv($from, $to, $value); } throw new \RuntimeException('No suitable convert encoding function (install the iconv or mbstring extension).'); } } PK]X[[Yaml/Parser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; use Symfony\Component\Yaml\Exception\ParseException; /** * Parser parses YAML strings to convert them to PHP arrays. * * @author Fabien Potencier */ class Parser { const FOLDED_SCALAR_PATTERN = '(?P\||>)(?P\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P +#.*)?'; private $offset = 0; private $lines = array(); private $currentLineNb = -1; private $currentLine = ''; private $refs = array(); /** * Constructor * * @param integer $offset The offset of YAML document (used for line numbers in error messages) */ public function __construct($offset = 0) { $this->offset = $offset; } /** * Parses a YAML string to a PHP value. * * @param string $value A YAML string * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return mixed A PHP value * * @throws ParseException If the YAML is not valid */ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = false) { $this->currentLineNb = -1; $this->currentLine = ''; $this->lines = explode("\n", $this->cleanup($value)); if (function_exists('mb_detect_encoding') && false === mb_detect_encoding($value, 'UTF-8', true)) { throw new ParseException('The YAML value does not appear to be valid UTF-8.'); } if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { $mbEncoding = mb_internal_encoding(); mb_internal_encoding('UTF-8'); } $data = array(); $context = null; while ($this->moveToNextLine()) { if ($this->isCurrentLineEmpty()) { continue; } // tab? if ("\t" === $this->currentLine[0]) { throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } $isRef = $isInPlace = $isProcessed = false; if (preg_match('#^\-((?P\s+)(?P.+?))?\s*$#u', $this->currentLine, $values)) { if ($context && 'mapping' == $context) { throw new ParseException('You cannot define a sequence item when in a mapping'); } $context = 'sequence'; if (isset($values['value']) && preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { $isRef = $matches['ref']; $values['value'] = $matches['value']; } // array if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { $c = $this->getRealCurrentLineNb() + 1; $parser = new Parser($c); $parser->refs =& $this->refs; $data[] = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport); } else { if (isset($values['leadspaces']) && ' ' == $values['leadspaces'] && preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P.+?))?\s*$#u', $values['value'], $matches) ) { // this is a compact notation element, add to next block and parse $c = $this->getRealCurrentLineNb(); $parser = new Parser($c); $parser->refs =& $this->refs; $block = $values['value']; if ($this->isNextLineIndented()) { $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + 2); } $data[] = $parser->parse($block, $exceptionOnInvalidType, $objectSupport); } else { $data[] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport); } } } elseif (preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P.+?))?\s*$#u', $this->currentLine, $values) && false === strpos($values['key'],' #')) { if ($context && 'sequence' == $context) { throw new ParseException('You cannot define a mapping item when in a sequence'); } $context = 'mapping'; // force correct settings Inline::parse(null, $exceptionOnInvalidType, $objectSupport); try { $key = Inline::parseScalar($values['key']); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); throw $e; } if ('<<' === $key) { if (isset($values['value']) && 0 === strpos($values['value'], '*')) { $isInPlace = substr($values['value'], 1); if (!array_key_exists($isInPlace, $this->refs)) { throw new ParseException(sprintf('Reference "%s" does not exist.', $isInPlace), $this->getRealCurrentLineNb() + 1, $this->currentLine); } } else { if (isset($values['value']) && $values['value'] !== '') { $value = $values['value']; } else { $value = $this->getNextEmbedBlock(); } $c = $this->getRealCurrentLineNb() + 1; $parser = new Parser($c); $parser->refs =& $this->refs; $parsed = $parser->parse($value, $exceptionOnInvalidType, $objectSupport); $merged = array(); if (!is_array($parsed)) { throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } elseif (isset($parsed[0])) { // Numeric array, merge individual elements foreach (array_reverse($parsed) as $parsedItem) { if (!is_array($parsedItem)) { throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem); } $merged = array_merge($parsedItem, $merged); } } else { // Associative array, merge $merged = array_merge($merged, $parsed); } $isProcessed = $merged; } } elseif (isset($values['value']) && preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { $isRef = $matches['ref']; $values['value'] = $matches['value']; } if ($isProcessed) { // Merge keys $data = $isProcessed; // hash } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { // if next line is less indented or equal, then it means that the current value is null if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) { $data[$key] = null; } else { $c = $this->getRealCurrentLineNb() + 1; $parser = new Parser($c); $parser->refs =& $this->refs; $data[$key] = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport); } } else { if ($isInPlace) { $data = $this->refs[$isInPlace]; } else { $data[$key] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport); } } } else { // 1-liner optionally followed by newline $lineCount = count($this->lines); if (1 === $lineCount || (2 === $lineCount && empty($this->lines[1]))) { try { $value = Inline::parse($this->lines[0], $exceptionOnInvalidType, $objectSupport); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); throw $e; } if (is_array($value)) { $first = reset($value); if (is_string($first) && 0 === strpos($first, '*')) { $data = array(); foreach ($value as $alias) { $data[] = $this->refs[substr($alias, 1)]; } $value = $data; } } if (isset($mbEncoding)) { mb_internal_encoding($mbEncoding); } return $value; } switch (preg_last_error()) { case PREG_INTERNAL_ERROR: $error = 'Internal PCRE error.'; break; case PREG_BACKTRACK_LIMIT_ERROR: $error = 'pcre.backtrack_limit reached.'; break; case PREG_RECURSION_LIMIT_ERROR: $error = 'pcre.recursion_limit reached.'; break; case PREG_BAD_UTF8_ERROR: $error = 'Malformed UTF-8 data.'; break; case PREG_BAD_UTF8_OFFSET_ERROR: $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.'; break; default: $error = 'Unable to parse.'; } throw new ParseException($error, $this->getRealCurrentLineNb() + 1, $this->currentLine); } if ($isRef) { $this->refs[$isRef] = end($data); } } if (isset($mbEncoding)) { mb_internal_encoding($mbEncoding); } return empty($data) ? null : $data; } /** * Returns the current line number (takes the offset into account). * * @return integer The current line number */ private function getRealCurrentLineNb() { return $this->currentLineNb + $this->offset; } /** * Returns the current line indentation. * * @return integer The current line indentation */ private function getCurrentLineIndentation() { return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' ')); } /** * Returns the next embed block of YAML. * * @param integer $indentation The indent level at which the block is to be read, or null for default * * @return string A YAML string * * @throws ParseException When indentation problem are detected */ private function getNextEmbedBlock($indentation = null) { $this->moveToNextLine(); if (null === $indentation) { $newIndent = $this->getCurrentLineIndentation(); $unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem($this->currentLine); if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) { throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } } else { $newIndent = $indentation; } $data = array(substr($this->currentLine, $newIndent)); $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem($this->currentLine); // Comments must not be removed inside a string block (ie. after a line ending with "|") $removeCommentsPattern = '~'.self::FOLDED_SCALAR_PATTERN.'$~'; $removeComments = !preg_match($removeCommentsPattern, $this->currentLine); while ($this->moveToNextLine()) { $indent = $this->getCurrentLineIndentation(); if ($indent === $newIndent) { $removeComments = !preg_match($removeCommentsPattern, $this->currentLine); } if ($isItUnindentedCollection && !$this->isStringUnIndentedCollectionItem($this->currentLine)) { $this->moveToPreviousLine(); break; } if ($this->isCurrentLineBlank()) { $data[] = substr($this->currentLine, $newIndent); continue; } if ($removeComments && $this->isCurrentLineComment()) { continue; } if ($indent >= $newIndent) { $data[] = substr($this->currentLine, $newIndent); } elseif (0 == $indent) { $this->moveToPreviousLine(); break; } else { throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } } return implode("\n", $data); } /** * Moves the parser to the next line. * * @return Boolean */ private function moveToNextLine() { if ($this->currentLineNb >= count($this->lines) - 1) { return false; } $this->currentLine = $this->lines[++$this->currentLineNb]; return true; } /** * Moves the parser to the previous line. */ private function moveToPreviousLine() { $this->currentLine = $this->lines[--$this->currentLineNb]; } /** * Parses a YAML value. * * @param string $value A YAML value * @param Boolean $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise * @param Boolean $objectSupport True if object support is enabled, false otherwise * * @return mixed A PHP value * * @throws ParseException When reference does not exist */ private function parseValue($value, $exceptionOnInvalidType, $objectSupport) { if (0 === strpos($value, '*')) { if (false !== $pos = strpos($value, '#')) { $value = substr($value, 1, $pos - 2); } else { $value = substr($value, 1); } if (!array_key_exists($value, $this->refs)) { throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLine); } return $this->refs[$value]; } if (preg_match('/^'.self::FOLDED_SCALAR_PATTERN.'$/', $value, $matches)) { $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), intval(abs($modifiers))); } try { return Inline::parse($value, $exceptionOnInvalidType, $objectSupport); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); throw $e; } } /** * Parses a folded scalar. * * @param string $separator The separator that was used to begin this folded scalar (| or >) * @param string $indicator The indicator that was used to begin this folded scalar (+ or -) * @param integer $indentation The indentation that was used to begin this folded scalar * * @return string The text value */ private function parseFoldedScalar($separator, $indicator = '', $indentation = 0) { $notEOF = $this->moveToNextLine(); if (!$notEOF) { return ''; } $isCurrentLineBlank = $this->isCurrentLineBlank(); $text = ''; // leading blank lines are consumed before determining indentation while ($notEOF && $isCurrentLineBlank) { // newline only if not EOF if ($notEOF = $this->moveToNextLine()) { $text .= "\n"; $isCurrentLineBlank = $this->isCurrentLineBlank(); } } // determine indentation if not specified if (0 === $indentation) { if (preg_match('/^ +/', $this->currentLine, $matches)) { $indentation = strlen($matches[0]); } } if ($indentation > 0) { $pattern = sprintf('/^ {%d}(.*)$/', $indentation); while ( $notEOF && ( $isCurrentLineBlank || preg_match($pattern, $this->currentLine, $matches) ) ) { if ($isCurrentLineBlank) { $text .= substr($this->currentLine, $indentation); } else { $text .= $matches[1]; } // newline only if not EOF if ($notEOF = $this->moveToNextLine()) { $text .= "\n"; $isCurrentLineBlank = $this->isCurrentLineBlank(); } } } elseif ($notEOF) { $text .= "\n"; } if ($notEOF) { $this->moveToPreviousLine(); } // replace all non-trailing single newlines with spaces in folded blocks if ('>' === $separator) { preg_match('/(\n*)$/', $text, $matches); $text = preg_replace('/(?getCurrentLineIndentation(); $EOF = !$this->moveToNextLine(); while (!$EOF && $this->isCurrentLineEmpty()) { $EOF = !$this->moveToNextLine(); } if ($EOF) { return false; } $ret = false; if ($this->getCurrentLineIndentation() > $currentIndentation) { $ret = true; } $this->moveToPreviousLine(); return $ret; } /** * Returns true if the current line is blank or if it is a comment line. * * @return Boolean Returns true if the current line is empty or if it is a comment line, false otherwise */ private function isCurrentLineEmpty() { return $this->isCurrentLineBlank() || $this->isCurrentLineComment(); } /** * Returns true if the current line is blank. * * @return Boolean Returns true if the current line is blank, false otherwise */ private function isCurrentLineBlank() { return '' == trim($this->currentLine, ' '); } /** * Returns true if the current line is a comment line. * * @return Boolean Returns true if the current line is a comment line, false otherwise */ private function isCurrentLineComment() { //checking explicitly the first char of the trim is faster than loops or strpos $ltrimmedLine = ltrim($this->currentLine, ' '); return $ltrimmedLine[0] === '#'; } /** * Cleanups a YAML string to be parsed. * * @param string $value The input YAML string * * @return string A cleaned up YAML string */ private function cleanup($value) { $value = str_replace(array("\r\n", "\r"), "\n", $value); // strip YAML header $count = 0; $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#su', '', $value, -1, $count); $this->offset += $count; // remove leading comments $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count); if ($count == 1) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; } // remove start of the document marker (---) $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count); if ($count == 1) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; // remove end of the document marker (...) $value = preg_replace('#\.\.\.\s*$#s', '', $value); } return $value; } /** * Returns true if the next line starts unindented collection * * @return Boolean Returns true if the next line starts unindented collection, false otherwise */ private function isNextLineUnIndentedCollection() { $currentIndentation = $this->getCurrentLineIndentation(); $notEOF = $this->moveToNextLine(); while ($notEOF && $this->isCurrentLineEmpty()) { $notEOF = $this->moveToNextLine(); } if (false === $notEOF) { return false; } $ret = false; if ( $this->getCurrentLineIndentation() == $currentIndentation && $this->isStringUnIndentedCollectionItem($this->currentLine) ) { $ret = true; } $this->moveToPreviousLine(); return $ret; } /** * Returns true if the string is un-indented collection item * * @return Boolean Returns true if the string is un-indented collection item, false otherwise */ private function isStringUnIndentedCollectionItem() { return (0 === strpos($this->currentLine, '- ')); } } PK])%,m m Yaml/Escaper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; /** * Escaper encapsulates escaping rules for single and double-quoted * YAML strings. * * @author Matthew Lewinski */ class Escaper { // Characters that would cause a dumped string to require double quoting. const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9"; // Mapping arrays for escaping a double quoted string. The backslash is // first to ensure proper escaping because str_replace operates iteratively // on the input arrays. This ordering of the characters avoids the use of strtr, // which performs more slowly. private static $escapees = array('\\\\', '\\"', '"', "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", "\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f", "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f", "\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9"); private static $escaped = array('\\"', '\\\\', '\\"', "\\0", "\\x01", "\\x02", "\\x03", "\\x04", "\\x05", "\\x06", "\\a", "\\b", "\\t", "\\n", "\\v", "\\f", "\\r", "\\x0e", "\\x0f", "\\x10", "\\x11", "\\x12", "\\x13", "\\x14", "\\x15", "\\x16", "\\x17", "\\x18", "\\x19", "\\x1a", "\\e", "\\x1c", "\\x1d", "\\x1e", "\\x1f", "\\N", "\\_", "\\L", "\\P"); /** * Determines if a PHP value would require double quoting in YAML. * * @param string $value A PHP value * * @return Boolean True if the value would require double quotes. */ public static function requiresDoubleQuoting($value) { return preg_match('/'.self::REGEX_CHARACTER_TO_ESCAPE.'/u', $value); } /** * Escapes and surrounds a PHP value with double quotes. * * @param string $value A PHP value * * @return string The quoted, escaped string */ public static function escapeWithDoubleQuotes($value) { return sprintf('"%s"', str_replace(self::$escapees, self::$escaped, $value)); } /** * Determines if a PHP value would require single quoting in YAML. * * @param string $value A PHP value * * @return Boolean True if the value would require single quotes. */ public static function requiresSingleQuoting($value) { return preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ \- ? | < > = ! % @ ` ]/x', $value); } /** * Escapes and surrounds a PHP value with single quotes. * * @param string $value A PHP value * * @return string The quoted, escaped string */ public static function escapeWithSingleQuotes($value) { return sprintf("'%s'", str_replace('\'', '\'\'', $value)); } } PK]8n Yaml/Dumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; /** * Dumper dumps PHP variables to YAML strings. * * @author Fabien Potencier */ class Dumper { /** * The amount of spaces to use for indentation of nested nodes. * * @var integer */ protected $indentation = 4; /** * Sets the indentation. * * @param integer $num The amount of spaces to use for indentation of nested nodes. */ public function setIndentation($num) { $this->indentation = (int) $num; } /** * Dumps a PHP value to YAML. * * @param mixed $input The PHP value * @param integer $inline The level where you switch to inline YAML * @param integer $indent The level of indentation (used internally) * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return string The YAML representation of the PHP value */ public function dump($input, $inline = 0, $indent = 0, $exceptionOnInvalidType = false, $objectSupport = false) { $output = ''; $prefix = $indent ? str_repeat(' ', $indent) : ''; if ($inline <= 0 || !is_array($input) || empty($input)) { $output .= $prefix.Inline::dump($input, $exceptionOnInvalidType, $objectSupport); } else { $isAHash = array_keys($input) !== range(0, count($input) - 1); foreach ($input as $key => $value) { $willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value); $output .= sprintf('%s%s%s%s', $prefix, $isAHash ? Inline::dump($key, $exceptionOnInvalidType, $objectSupport).':' : '-', $willBeInlined ? ' ' : "\n", $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $exceptionOnInvalidType, $objectSupport) ).($willBeInlined ? "\n" : ''); } } return $output; } } PK]q+3??Yaml/Inline.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Exception\DumpException; /** * Inline implements a YAML parser/dumper for the YAML inline syntax. * * @author Fabien Potencier */ class Inline { const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')'; private static $exceptionOnInvalidType = false; private static $objectSupport = false; /** * Converts a YAML string to a PHP array. * * @param string $value A YAML string * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return array A PHP array representing the YAML string * * @throws ParseException */ public static function parse($value, $exceptionOnInvalidType = false, $objectSupport = false) { self::$exceptionOnInvalidType = $exceptionOnInvalidType; self::$objectSupport = $objectSupport; $value = trim($value); if (0 == strlen($value)) { return ''; } if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { $mbEncoding = mb_internal_encoding(); mb_internal_encoding('ASCII'); } $i = 0; switch ($value[0]) { case '[': $result = self::parseSequence($value, $i); ++$i; break; case '{': $result = self::parseMapping($value, $i); ++$i; break; default: $result = self::parseScalar($value, null, array('"', "'"), $i); } // some comments are allowed at the end if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) { throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i))); } if (isset($mbEncoding)) { mb_internal_encoding($mbEncoding); } return $result; } /** * Dumps a given PHP variable to a YAML string. * * @param mixed $value The PHP variable to convert * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return string The YAML string representing the PHP array * * @throws DumpException When trying to dump PHP resource */ public static function dump($value, $exceptionOnInvalidType = false, $objectSupport = false) { switch (true) { case is_resource($value): if ($exceptionOnInvalidType) { throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value))); } return 'null'; case is_object($value): if ($objectSupport) { return '!!php/object:'.serialize($value); } if ($exceptionOnInvalidType) { throw new DumpException('Object support when dumping a YAML file has been disabled.'); } return 'null'; case is_array($value): return self::dumpArray($value, $exceptionOnInvalidType, $objectSupport); case null === $value: return 'null'; case true === $value: return 'true'; case false === $value: return 'false'; case ctype_digit($value): return is_string($value) ? "'$value'" : (int) $value; case is_numeric($value): $locale = setlocale(LC_NUMERIC, 0); if (false !== $locale) { setlocale(LC_NUMERIC, 'C'); } $repr = is_string($value) ? "'$value'" : (is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : strval($value)); if (false !== $locale) { setlocale(LC_NUMERIC, $locale); } return $repr; case Escaper::requiresDoubleQuoting($value): return Escaper::escapeWithDoubleQuotes($value); case Escaper::requiresSingleQuoting($value): return Escaper::escapeWithSingleQuotes($value); case '' == $value: return "''"; case preg_match(self::getTimestampRegex(), $value): case in_array(strtolower($value), array('null', '~', 'true', 'false')): return "'$value'"; default: return $value; } } /** * Dumps a PHP array to a YAML string. * * @param array $value The PHP array to dump * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return string The YAML string representing the PHP array */ private static function dumpArray($value, $exceptionOnInvalidType, $objectSupport) { // array $keys = array_keys($value); if ((1 == count($keys) && '0' == $keys[0]) || (count($keys) > 1 && array_reduce($keys, function ($v, $w) { return (integer) $v + $w; }, 0) == count($keys) * (count($keys) - 1) / 2) ) { $output = array(); foreach ($value as $val) { $output[] = self::dump($val, $exceptionOnInvalidType, $objectSupport); } return sprintf('[%s]', implode(', ', $output)); } // mapping $output = array(); foreach ($value as $key => $val) { $output[] = sprintf('%s: %s', self::dump($key, $exceptionOnInvalidType, $objectSupport), self::dump($val, $exceptionOnInvalidType, $objectSupport)); } return sprintf('{ %s }', implode(', ', $output)); } /** * Parses a scalar to a YAML string. * * @param scalar $scalar * @param string $delimiters * @param array $stringDelimiters * @param integer &$i * @param Boolean $evaluate * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ public static function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true) { if (in_array($scalar[$i], $stringDelimiters)) { // quoted scalar $output = self::parseQuotedScalar($scalar, $i); if (null !== $delimiters) { $tmp = ltrim(substr($scalar, $i), ' '); if (!in_array($tmp[0], $delimiters)) { throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i))); } } } else { // "normal" string if (!$delimiters) { $output = substr($scalar, $i); $i += strlen($output); // remove comments if (false !== $strpos = strpos($output, ' #')) { $output = rtrim(substr($output, 0, $strpos)); } } elseif (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { $output = $match[1]; $i += strlen($output); } else { throw new ParseException(sprintf('Malformed inline YAML string (%s).', $scalar)); } if ($evaluate) { $output = self::evaluateScalar($output); } } return $output; } /** * Parses a quoted scalar to YAML. * * @param string $scalar * @param integer &$i * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ private static function parseQuotedScalar($scalar, &$i) { if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { throw new ParseException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i))); } $output = substr($match[0], 1, strlen($match[0]) - 2); $unescaper = new Unescaper(); if ('"' == $scalar[$i]) { $output = $unescaper->unescapeDoubleQuotedString($output); } else { $output = $unescaper->unescapeSingleQuotedString($output); } $i += strlen($match[0]); return $output; } /** * Parses a sequence to a YAML string. * * @param string $sequence * @param integer &$i * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ private static function parseSequence($sequence, &$i = 0) { $output = array(); $len = strlen($sequence); $i += 1; // [foo, bar, ...] while ($i < $len) { switch ($sequence[$i]) { case '[': // nested sequence $output[] = self::parseSequence($sequence, $i); break; case '{': // nested mapping $output[] = self::parseMapping($sequence, $i); break; case ']': return $output; case ',': case ' ': break; default: $isQuoted = in_array($sequence[$i], array('"', "'")); $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i); if (!$isQuoted && false !== strpos($value, ': ')) { // embedded mapping? try { $value = self::parseMapping('{'.$value.'}'); } catch (\InvalidArgumentException $e) { // no, it's not } } $output[] = $value; --$i; } ++$i; } throw new ParseException(sprintf('Malformed inline YAML string %s', $sequence)); } /** * Parses a mapping to a YAML string. * * @param string $mapping * @param integer &$i * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ private static function parseMapping($mapping, &$i = 0) { $output = array(); $len = strlen($mapping); $i += 1; // {foo: bar, bar:foo, ...} while ($i < $len) { switch ($mapping[$i]) { case ' ': case ',': ++$i; continue 2; case '}': return $output; } // key $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false); // value $done = false; while ($i < $len) { switch ($mapping[$i]) { case '[': // nested sequence $output[$key] = self::parseSequence($mapping, $i); $done = true; break; case '{': // nested mapping $output[$key] = self::parseMapping($mapping, $i); $done = true; break; case ':': case ' ': break; default: $output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i); $done = true; --$i; } ++$i; if ($done) { continue 2; } } } throw new ParseException(sprintf('Malformed inline YAML string %s', $mapping)); } /** * Evaluates scalars and replaces magic values. * * @param string $scalar * * @return string A YAML string */ private static function evaluateScalar($scalar) { $scalar = trim($scalar); $scalarLower = strtolower($scalar); switch (true) { case 'null' === $scalarLower: case '' === $scalar: case '~' === $scalar: return null; case 'true' === $scalarLower: return true; case 'false' === $scalarLower: return false; // Optimise for returning strings. case $scalar[0] === '+' || $scalar[0] === '-' || $scalar[0] === '.' || $scalar[0] === '!' || is_numeric($scalar[0]): switch (true) { case 0 === strpos($scalar, '!str'): return (string) substr($scalar, 5); case 0 === strpos($scalar, '! '): return intval(self::parseScalar(substr($scalar, 2))); case 0 === strpos($scalar, '!!php/object:'): if (self::$objectSupport) { return unserialize(substr($scalar, 13)); } if (self::$exceptionOnInvalidType) { throw new ParseException('Object support when parsing a YAML file has been disabled.'); } return null; case ctype_digit($scalar): $raw = $scalar; $cast = intval($scalar); return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw); case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)): $raw = $scalar; $cast = intval($scalar); return '0' == $scalar[1] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw); case is_numeric($scalar): return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar); case '.inf' === $scalarLower: case '.nan' === $scalarLower: return -log(0); case '-.inf' === $scalarLower: return log(0); case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar): return floatval(str_replace(',', '', $scalar)); case preg_match(self::getTimestampRegex(), $scalar): return strtotime($scalar); } default: return (string) $scalar; } } /** * Gets a regex that matches a YAML date. * * @return string The regular expression * * @see http://www.yaml.org/spec/1.2/spec.html#id2761573 */ private static function getTimestampRegex() { return <<[0-9][0-9][0-9][0-9]) -(?P[0-9][0-9]?) -(?P[0-9][0-9]?) (?:(?:[Tt]|[ \t]+) (?P[0-9][0-9]?) :(?P[0-9][0-9]) :(?P[0-9][0-9]) (?:\.(?P[0-9]*))? (?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?) (?::(?P[0-9][0-9]))?))?)? $~x EOF; } } PK]7MӺ  Yaml/Yaml.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; use Symfony\Component\Yaml\Exception\ParseException; /** * Yaml offers convenience methods to load and dump YAML. * * @author Fabien Potencier * * @api */ class Yaml { /** * Parses YAML into a PHP array. * * The parse method, when supplied with a YAML stream (string or file), * will do its best to convert YAML in a file into a PHP array. * * Usage: * * $array = Yaml::parse('config.yml'); * print_r($array); * * * As this method accepts both plain strings and file names as an input, * you must validate the input before calling this method. Passing a file * as an input is a deprecated feature and will be removed in 3.0. * * @param string $input Path to a YAML file or a string containing YAML * @param Boolean $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise * @param Boolean $objectSupport True if object support is enabled, false otherwise * * @return array The YAML converted to a PHP array * * @throws ParseException If the YAML is not valid * * @api */ public static function parse($input, $exceptionOnInvalidType = false, $objectSupport = false) { // if input is a file, process it $file = ''; if (strpos($input, "\n") === false && is_file($input)) { if (false === is_readable($input)) { throw new ParseException(sprintf('Unable to parse "%s" as the file is not readable.', $input)); } $file = $input; $input = file_get_contents($file); } $yaml = new Parser(); try { return $yaml->parse($input, $exceptionOnInvalidType, $objectSupport); } catch (ParseException $e) { if ($file) { $e->setParsedFile($file); } throw $e; } } /** * Dumps a PHP array to a YAML string. * * The dump method, when supplied with an array, will do its best * to convert the array into friendly YAML. * * @param array $array PHP array * @param integer $inline The level where you switch to inline YAML * @param integer $indent The amount of spaces to use for indentation of nested nodes. * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return string A YAML string representing the original PHP array * * @api */ public static function dump($array, $inline = 2, $indent = 4, $exceptionOnInvalidType = false, $objectSupport = false) { $yaml = new Dumper(); $yaml->setIndentation($indent); return $yaml->dump($array, $inline, 0, $exceptionOnInvalidType, $objectSupport); } } PK]+l%Yaml/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; /** * Exception interface for all exceptions thrown by the component. * * @author Fabien Potencier * * @api */ interface ExceptionInterface { } PK]|-#Yaml/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; /** * Exception class thrown when an error occurs during parsing. * * @author Romain Neutron * * @api */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK] !Yaml/Exception/ParseException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; if (!defined('JSON_UNESCAPED_UNICODE')) { define('JSON_UNESCAPED_SLASHES', 64); define('JSON_UNESCAPED_UNICODE', 256); } /** * Exception class thrown when an error occurs during parsing. * * @author Fabien Potencier * * @api */ class ParseException extends RuntimeException { private $parsedFile; private $parsedLine; private $snippet; private $rawMessage; /** * Constructor. * * @param string $message The error message * @param integer $parsedLine The line where the error occurred * @param integer $snippet The snippet of code near the problem * @param string $parsedFile The file name where the error occurred * @param \Exception $previous The previous exception */ public function __construct($message, $parsedLine = -1, $snippet = null, $parsedFile = null, \Exception $previous = null) { $this->parsedFile = $parsedFile; $this->parsedLine = $parsedLine; $this->snippet = $snippet; $this->rawMessage = $message; $this->updateRepr(); parent::__construct($this->message, 0, $previous); } /** * Gets the snippet of code near the error. * * @return string The snippet of code */ public function getSnippet() { return $this->snippet; } /** * Sets the snippet of code near the error. * * @param string $snippet The code snippet */ public function setSnippet($snippet) { $this->snippet = $snippet; $this->updateRepr(); } /** * Gets the filename where the error occurred. * * This method returns null if a string is parsed. * * @return string The filename */ public function getParsedFile() { return $this->parsedFile; } /** * Sets the filename where the error occurred. * * @param string $parsedFile The filename */ public function setParsedFile($parsedFile) { $this->parsedFile = $parsedFile; $this->updateRepr(); } /** * Gets the line where the error occurred. * * @return integer The file line */ public function getParsedLine() { return $this->parsedLine; } /** * Sets the line where the error occurred. * * @param integer $parsedLine The file line */ public function setParsedLine($parsedLine) { $this->parsedLine = $parsedLine; $this->updateRepr(); } private function updateRepr() { $this->message = $this->rawMessage; $dot = false; if ('.' === substr($this->message, -1)) { $this->message = substr($this->message, 0, -1); $dot = true; } if (null !== $this->parsedFile) { $this->message .= sprintf(' in %s', json_encode($this->parsedFile, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); } if ($this->parsedLine >= 0) { $this->message .= sprintf(' at line %d', $this->parsedLine); } if ($this->snippet) { $this->message .= sprintf(' (near "%s")', $this->snippet); } if ($dot) { $this->message .= '.'; } } } PK]ؙ՚ Yaml/Exception/DumpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; /** * Exception class thrown when an error occurs during dumping. * * @author Fabien Potencier * * @api */ class DumpException extends RuntimeException { } PK]bNNYaml/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * EngineInterface is the interface each engine must implement. * * All methods relies on a template name. A template name is a * "logical" name for the template, and as such it does not refer to * a path on the filesystem (in fact, the template can be stored * anywhere, like in a database). * * The methods should accept any name. If the name is not an instance of * TemplateReferenceInterface, a TemplateNameParserInterface should be used to * convert the name to a TemplateReferenceInterface instance. * * Each template loader uses the logical template name to look for * the template. * * @author Fabien Potencier * * @api */ interface EngineInterface { /** * Renders a template. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * @param array $parameters An array of parameters to pass to the template * * @return string The evaluated template as a string * * @throws \RuntimeException if the template cannot be rendered * * @api */ public function render($name, array $parameters = array()); /** * Returns true if the template exists. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * * @return Boolean true if the template exists, false otherwise * * @throws \RuntimeException if the engine cannot handle the template name * * @api */ public function exists($name); /** * Returns true if this class is able to render the given template. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * * @return Boolean true if this class supports the given template, false otherwise * * @api */ public function supports($name); } PK]C'Templating/StreamingEngineInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * StreamingEngineInterface provides a method that knows how to stream a template. * * @author Fabien Potencier */ interface StreamingEngineInterface { /** * Streams a template. * * The implementation should output the content directly to the client. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * @param array $parameters An array of parameters to pass to the template * * @throws \RuntimeException if the template cannot be rendered * @throws \LogicException if the template cannot be streamed */ public function stream($name, array $parameters = array()); } PK]NOTemplating/Helper/Helper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Helper; /** * Helper is the base class for all helper classes. * * Most of the time, a Helper is an adapter around an existing * class that exposes a read-only interface for templates. * * @author Fabien Potencier * * @api */ abstract class Helper implements HelperInterface { protected $charset = 'UTF-8'; /** * Sets the default charset. * * @param string $charset The charset * * @api */ public function setCharset($charset) { $this->charset = $charset; } /** * Gets the default charset. * * @return string The default charset * * @api */ public function getCharset() { return $this->charset; } } PK]V¤՟"Templating/Helper/AssetsHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Helper; use Symfony\Component\Templating\Asset\PathPackage; use Symfony\Component\Templating\Asset\UrlPackage; /** * AssetsHelper helps manage asset URLs. * * Usage: * * * * * * @author Fabien Potencier * @author Kris Wallsmith */ class AssetsHelper extends CoreAssetsHelper { /** * Constructor. * * @param string $basePath The base path * @param string|array $baseUrls Base asset URLs * @param string $version The asset version * @param string $format The version format * @param array $namedPackages Additional packages */ public function __construct($basePath = null, $baseUrls = array(), $version = null, $format = null, $namedPackages = array()) { if ($baseUrls) { $defaultPackage = new UrlPackage($baseUrls, $version, $format); } else { $defaultPackage = new PathPackage($basePath, $version, $format); } parent::__construct($defaultPackage, $namedPackages); } } PK] &Templating/Helper/CoreAssetsHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Helper; use Symfony\Component\Templating\Asset\PackageInterface; /** * CoreAssetsHelper helps manage asset URLs. * * Usage: * * * * * * @author Fabien Potencier * @author Kris Wallsmith */ class CoreAssetsHelper extends Helper implements PackageInterface { protected $defaultPackage; protected $namedPackages = array(); /** * Constructor. * * @param PackageInterface $defaultPackage The default package * @param array $namedPackages Additional packages indexed by name */ public function __construct(PackageInterface $defaultPackage, array $namedPackages = array()) { $this->defaultPackage = $defaultPackage; foreach ($namedPackages as $name => $package) { $this->addPackage($name, $package); } } /** * Sets the default package. * * @param PackageInterface $defaultPackage The default package */ public function setDefaultPackage(PackageInterface $defaultPackage) { $this->defaultPackage = $defaultPackage; } /** * Adds an asset package to the helper. * * @param string $name The package name * @param PackageInterface $package The package */ public function addPackage($name, PackageInterface $package) { $this->namedPackages[$name] = $package; } /** * Returns an asset package. * * @param string $name The name of the package or null for the default package * * @return PackageInterface An asset package * * @throws \InvalidArgumentException If there is no package by that name */ public function getPackage($name = null) { if (null === $name) { return $this->defaultPackage; } if (!isset($this->namedPackages[$name])) { throw new \InvalidArgumentException(sprintf('There is no "%s" asset package.', $name)); } return $this->namedPackages[$name]; } /** * Gets the version to add to public URL. * * @param string $packageName A package name * * @return string The current version */ public function getVersion($packageName = null) { return $this->getPackage($packageName)->getVersion(); } /** * Returns the public path. * * Absolute paths (i.e. http://...) are returned unmodified. * * @param string $path A public path * @param string $packageName The name of the asset package to use * * @return string A public path which takes into account the base path and URL path */ public function getUrl($path, $packageName = null) { return $this->getPackage($packageName)->getUrl($path); } /** * Returns the canonical name of this helper. * * @return string The canonical name */ public function getName() { return 'assets'; } } PK]+rm m !Templating/Helper/SlotsHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Helper; /** * SlotsHelper manages template slots. * * @author Fabien Potencier * * @api */ class SlotsHelper extends Helper { protected $slots = array(); protected $openSlots = array(); /** * Starts a new slot. * * This method starts an output buffer that will be * closed when the stop() method is called. * * @param string $name The slot name * * @throws \InvalidArgumentException if a slot with the same name is already started * * @api */ public function start($name) { if (in_array($name, $this->openSlots)) { throw new \InvalidArgumentException(sprintf('A slot named "%s" is already started.', $name)); } $this->openSlots[] = $name; $this->slots[$name] = ''; ob_start(); ob_implicit_flush(0); } /** * Stops a slot. * * @throws \LogicException if no slot has been started * * @api */ public function stop() { if (!$this->openSlots) { throw new \LogicException('No slot started.'); } $name = array_pop($this->openSlots); $this->slots[$name] = ob_get_clean(); } /** * Returns true if the slot exists. * * @param string $name The slot name * * @return Boolean * * @api */ public function has($name) { return isset($this->slots[$name]); } /** * Gets the slot value. * * @param string $name The slot name * @param Boolean|string $default The default slot content * * @return string The slot content * * @api */ public function get($name, $default = false) { return isset($this->slots[$name]) ? $this->slots[$name] : $default; } /** * Sets a slot value. * * @param string $name The slot name * @param string $content The slot content * * @api */ public function set($name, $content) { $this->slots[$name] = $content; } /** * Outputs a slot. * * @param string $name The slot name * @param Boolean|string $default The default slot content * * @return Boolean true if the slot is defined or if a default content has been provided, false otherwise * * @api */ public function output($name, $default = false) { if (!isset($this->slots[$name])) { if (false !== $default) { echo $default; return true; } return false; } echo $this->slots[$name]; return true; } /** * Returns the canonical name of this helper. * * @return string The canonical name * * @api */ public function getName() { return 'slots'; } } PK]Է%Templating/Helper/HelperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Helper; /** * HelperInterface is the interface all helpers must implement. * * @author Fabien Potencier * * @api */ interface HelperInterface { /** * Returns the canonical name of this helper. * * @return string The canonical name * * @api */ public function getName(); /** * Sets the default charset. * * @param string $charset The charset * * @api */ public function setCharset($charset); /** * Gets the default charset. * * @return string The default charset * * @api */ public function getCharset(); } PK]'"Templating/Storage/FileStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Storage; /** * FileStorage represents a template stored on the filesystem. * * @author Fabien Potencier * * @api */ class FileStorage extends Storage { /** * Returns the content of the template. * * @return string The template content * * @api */ public function getContent() { return file_get_contents($this->template); } } PK]π\Templating/Storage/Storage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Storage; /** * Storage is the base class for all storage classes. * * @author Fabien Potencier * * @api */ abstract class Storage { protected $template; /** * Constructor. * * @param string $template The template name * * @api */ public function __construct($template) { $this->template = $template; } /** * Returns the object string representation. * * @return string The template name */ public function __toString() { return (string) $this->template; } /** * Returns the content of the template. * * @return string The template content * * @api */ abstract public function getContent(); } PK]("w$Templating/Storage/StringStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Storage; /** * StringStorage represents a template stored in a string. * * @author Fabien Potencier * * @api */ class StringStorage extends Storage { /** * Returns the content of the template. * * @return string The template content * * @api */ public function getContent() { return $this->template; } } PK]?w y=y=Templating/PhpEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; use Symfony\Component\Templating\Storage\Storage; use Symfony\Component\Templating\Storage\FileStorage; use Symfony\Component\Templating\Storage\StringStorage; use Symfony\Component\Templating\Helper\HelperInterface; use Symfony\Component\Templating\Loader\LoaderInterface; if (!defined('ENT_SUBSTITUTE')) { define('ENT_SUBSTITUTE', 8); } /** * PhpEngine is an engine able to render PHP templates. * * @author Fabien Potencier * * @api */ class PhpEngine implements EngineInterface, \ArrayAccess { protected $loader; protected $current; protected $helpers = array(); protected $parents = array(); protected $stack = array(); protected $charset = 'UTF-8'; protected $cache = array(); protected $escapers = array(); protected static $escaperCache = array(); protected $globals = array(); protected $parser; private $evalTemplate; private $evalParameters; /** * Constructor. * * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance * @param LoaderInterface $loader A loader instance * @param HelperInterface[] $helpers An array of helper instances */ public function __construct(TemplateNameParserInterface $parser, LoaderInterface $loader, array $helpers = array()) { $this->parser = $parser; $this->loader = $loader; $this->addHelpers($helpers); $this->initializeEscapers(); foreach ($this->escapers as $context => $escaper) { $this->setEscaper($context, $escaper); } } /** * {@inheritdoc} * * @throws \InvalidArgumentException if the template does not exist * * @api */ public function render($name, array $parameters = array()) { $storage = $this->load($name); $key = hash('sha256', serialize($storage)); $this->current = $key; $this->parents[$key] = null; // attach the global variables $parameters = array_replace($this->getGlobals(), $parameters); // render if (false === $content = $this->evaluate($storage, $parameters)) { throw new \RuntimeException(sprintf('The template "%s" cannot be rendered.', $this->parser->parse($name))); } // decorator if ($this->parents[$key]) { $slots = $this->get('slots'); $this->stack[] = $slots->get('_content'); $slots->set('_content', $content); $content = $this->render($this->parents[$key], $parameters); $slots->set('_content', array_pop($this->stack)); } return $content; } /** * {@inheritdoc} * * @api */ public function exists($name) { try { $this->load($name); } catch (\InvalidArgumentException $e) { return false; } return true; } /** * {@inheritdoc} * * @api */ public function supports($name) { $template = $this->parser->parse($name); return 'php' === $template->get('engine'); } /** * Evaluates a template. * * @param Storage $template The template to render * @param array $parameters An array of parameters to pass to the template * * @return string|false The evaluated template, or false if the engine is unable to render the template * * @throws \InvalidArgumentException */ protected function evaluate(Storage $template, array $parameters = array()) { $this->evalTemplate = $template; $this->evalParameters = $parameters; unset($template, $parameters); if (isset($this->evalParameters['this'])) { throw new \InvalidArgumentException('Invalid parameter (this)'); } if (isset($this->evalParameters['view'])) { throw new \InvalidArgumentException('Invalid parameter (view)'); } $view = $this; if ($this->evalTemplate instanceof FileStorage) { extract($this->evalParameters, EXTR_SKIP); $this->evalParameters = null; ob_start(); require $this->evalTemplate; $this->evalTemplate = null; return ob_get_clean(); } elseif ($this->evalTemplate instanceof StringStorage) { extract($this->evalParameters, EXTR_SKIP); $this->evalParameters = null; ob_start(); eval('; ?>'.$this->evalTemplate.'evalTemplate = null; return ob_get_clean(); } return false; } /** * Gets a helper value. * * @param string $name The helper name * * @return HelperInterface The helper value * * @throws \InvalidArgumentException if the helper is not defined * * @api */ public function offsetGet($name) { return $this->get($name); } /** * Returns true if the helper is defined. * * @param string $name The helper name * * @return Boolean true if the helper is defined, false otherwise * * @api */ public function offsetExists($name) { return isset($this->helpers[$name]); } /** * Sets a helper. * * @param HelperInterface $name The helper instance * @param string $value An alias * * @api */ public function offsetSet($name, $value) { $this->set($name, $value); } /** * Removes a helper. * * @param string $name The helper name * * @throws \LogicException * * @api */ public function offsetUnset($name) { throw new \LogicException(sprintf('You can\'t unset a helper (%s).', $name)); } /** * Adds some helpers. * * @param HelperInterface[] $helpers An array of helper * * @api */ public function addHelpers(array $helpers) { foreach ($helpers as $alias => $helper) { $this->set($helper, is_int($alias) ? null : $alias); } } /** * Sets the helpers. * * @param HelperInterface[] $helpers An array of helper * * @api */ public function setHelpers(array $helpers) { $this->helpers = array(); $this->addHelpers($helpers); } /** * Sets a helper. * * @param HelperInterface $helper The helper instance * @param string $alias An alias * * @api */ public function set(HelperInterface $helper, $alias = null) { $this->helpers[$helper->getName()] = $helper; if (null !== $alias) { $this->helpers[$alias] = $helper; } $helper->setCharset($this->charset); } /** * Returns true if the helper if defined. * * @param string $name The helper name * * @return Boolean true if the helper is defined, false otherwise * * @api */ public function has($name) { return isset($this->helpers[$name]); } /** * Gets a helper value. * * @param string $name The helper name * * @return HelperInterface The helper instance * * @throws \InvalidArgumentException if the helper is not defined * * @api */ public function get($name) { if (!isset($this->helpers[$name])) { throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); } return $this->helpers[$name]; } /** * Decorates the current template with another one. * * @param string $template The decorator logical name * * @api */ public function extend($template) { $this->parents[$this->current] = $template; } /** * Escapes a string by using the current charset. * * @param mixed $value A variable to escape * @param string $context The context name * * @return string The escaped value * * @api */ public function escape($value, $context = 'html') { if (is_numeric($value)) { return $value; } // If we deal with a scalar value, we can cache the result to increase // the performance when the same value is escaped multiple times (e.g. loops) if (is_scalar($value)) { if (!isset(self::$escaperCache[$context][$value])) { self::$escaperCache[$context][$value] = call_user_func($this->getEscaper($context), $value); } return self::$escaperCache[$context][$value]; } return call_user_func($this->getEscaper($context), $value); } /** * Sets the charset to use. * * @param string $charset The charset * * @api */ public function setCharset($charset) { $this->charset = $charset; } /** * Gets the current charset. * * @return string The current charset * * @api */ public function getCharset() { return $this->charset; } /** * Adds an escaper for the given context. * * @param string $context The escaper context (html, js, ...) * @param mixed $escaper A PHP callable * * @api */ public function setEscaper($context, $escaper) { $this->escapers[$context] = $escaper; self::$escaperCache[$context] = array(); } /** * Gets an escaper for a given context. * * @param string $context The context name * * @return mixed $escaper A PHP callable * * @throws \InvalidArgumentException * * @api */ public function getEscaper($context) { if (!isset($this->escapers[$context])) { throw new \InvalidArgumentException(sprintf('No registered escaper for context "%s".', $context)); } return $this->escapers[$context]; } /** * @param string $name * @param mixed $value * * @api */ public function addGlobal($name, $value) { $this->globals[$name] = $value; } /** * Returns the assigned globals. * * @return array * * @api */ public function getGlobals() { return $this->globals; } /** * Initializes the built-in escapers. * * Each function specifies a way for applying a transformation to a string * passed to it. The purpose is for the string to be "escaped" so it is * suitable for the format it is being displayed in. * * For example, the string: "It's required that you enter a username & password.\n" * If this were to be displayed as HTML it would be sensible to turn the * ampersand into '&' and the apostrophe into '&aps;'. However if it were * going to be used as a string in JavaScript to be displayed in an alert box * it would be right to leave the string as-is, but c-escape the apostrophe and * the new line. * * For each function there is a define to avoid problems with strings being * incorrectly specified. */ protected function initializeEscapers() { $that = $this; $this->escapers = array( 'html' => /** * Runs the PHP function htmlspecialchars on the value passed. * * @param string $value the value to escape * * @return string the escaped value */ function ($value) use ($that) { // Numbers and Boolean values get turned into strings which can cause problems // with type comparisons (e.g. === or is_int() etc). return is_string($value) ? htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, $that->getCharset(), false) : $value; }, 'js' => /** * A function that escape all non-alphanumeric characters * into their \xHH or \uHHHH representations * * @param string $value the value to escape * @return string the escaped value */ function ($value) use ($that) { if ('UTF-8' != $that->getCharset()) { $value = $that->convertEncoding($value, 'UTF-8', $that->getCharset()); } $callback = function ($matches) use ($that) { $char = $matches[0]; // \xHH if (!isset($char[1])) { return '\\x'.substr('00'.bin2hex($char), -2); } // \uHHHH $char = $that->convertEncoding($char, 'UTF-16BE', 'UTF-8'); return '\\u'.substr('0000'.bin2hex($char), -4); }; if (null === $value = preg_replace_callback('#[^\p{L}\p{N} ]#u', $callback, $value)) { throw new \InvalidArgumentException('The string to escape is not a valid UTF-8 string.'); } if ('UTF-8' != $that->getCharset()) { $value = $that->convertEncoding($value, $that->getCharset(), 'UTF-8'); } return $value; }, ); self::$escaperCache = array(); } /** * Convert a string from one encoding to another. * * @param string $string The string to convert * @param string $to The input encoding * @param string $from The output encoding * * @return string The string with the new encoding * * @throws \RuntimeException if no suitable encoding function is found (iconv or mbstring) */ public function convertEncoding($string, $to, $from) { if (function_exists('mb_convert_encoding')) { return mb_convert_encoding($string, $to, $from); } elseif (function_exists('iconv')) { return iconv($from, $to, $string); } throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).'); } /** * Gets the loader associated with this engine. * * @return LoaderInterface A LoaderInterface instance */ public function getLoader() { return $this->loader; } /** * Loads the given template. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * * @return Storage A Storage instance * * @throws \InvalidArgumentException if the template cannot be found */ protected function load($name) { $template = $this->parser->parse($name); $key = $template->getLogicalName(); if (isset($this->cache[$key])) { return $this->cache[$key]; } $storage = $this->loader->load($template); if (false === $storage) { throw new \InvalidArgumentException(sprintf('The template "%s" does not exist.', $template)); } return $this->cache[$key] = $storage; } } PK]pvj%Templating/Asset/PackageInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Asset; /** * Asset package interface. * * @author Kris Wallsmith */ interface PackageInterface { /** * Returns the asset package version. * * @return string The version string */ public function getVersion(); /** * Returns an absolute or root-relative public path. * * @param string $path A path * * @return string The public path */ public function getUrl($path); } PK]TTTemplating/Asset/UrlPackage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Asset; /** * The URL packages adds a version and a base URL to asset URLs. * * @author Kris Wallsmith */ class UrlPackage extends Package { private $baseUrls; /** * Constructor. * * @param string|array $baseUrls Base asset URLs * @param string $version The package version * @param string $format The format used to apply the version */ public function __construct($baseUrls = array(), $version = null, $format = null) { parent::__construct($version, $format); if (!is_array($baseUrls)) { $baseUrls = (array) $baseUrls; } $this->baseUrls = array(); foreach ($baseUrls as $baseUrl) { $this->baseUrls[] = rtrim($baseUrl, '/'); } } public function getUrl($path) { if (false !== strpos($path, '://') || 0 === strpos($path, '//')) { return $path; } $url = $this->applyVersion($path); if ($url && '/' != $url[0]) { $url = '/'.$url; } return $this->getBaseUrl($path).$url; } /** * Returns the base URL for a path. * * @param string $path * * @return string The base URL */ public function getBaseUrl($path) { switch ($count = count($this->baseUrls)) { case 0: return ''; case 1: return $this->baseUrls[0]; default: return $this->baseUrls[fmod(hexdec(substr(hash('sha256', $path), 0, 10)), $count)]; } } } PK]bNN Templating/Asset/PathPackage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Asset; /** * The path packages adds a version and a base path to asset URLs. * * @author Kris Wallsmith */ class PathPackage extends Package { private $basePath; /** * Constructor. * * @param string $basePath The base path to be prepended to relative paths * @param string $version The package version * @param string $format The format used to apply the version */ public function __construct($basePath = null, $version = null, $format = null) { parent::__construct($version, $format); if (!$basePath) { $this->basePath = '/'; } else { if ('/' != $basePath[0]) { $basePath = '/'.$basePath; } $this->basePath = rtrim($basePath, '/').'/'; } } public function getUrl($path) { if (false !== strpos($path, '://') || 0 === strpos($path, '//')) { return $path; } $url = $this->applyVersion($path); // apply the base path if ('/' !== substr($url, 0, 1)) { $url = $this->basePath.$url; } return $url; } /** * Returns the base path. * * @return string The base path */ public function getBasePath() { return $this->basePath; } } PK]o##Templating/Asset/Package.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Asset; /** * The basic package will add a version to asset URLs. * * @author Kris Wallsmith */ class Package implements PackageInterface { private $version; private $format; /** * Constructor. * * @param string $version The package version * @param string $format The format used to apply the version */ public function __construct($version = null, $format = '') { $this->version = $version; $this->format = $format ?: '%s?%s'; } public function getVersion() { return $this->version; } public function getUrl($path) { if (false !== strpos($path, '://') || 0 === strpos($path, '//')) { return $path; } return $this->applyVersion($path); } /** * Applies version to the supplied path. * * @param string $path A path * * @return string The versionized path */ protected function applyVersion($path) { if (null === $this->version) { return $path; } $versionized = sprintf($this->format, ltrim($path, '/'), $this->version); if ($path && '/' == $path[0]) { $versionized = '/'.$versionized; } return $versionized; } } PK]_6H  Templating/DelegatingEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * DelegatingEngine selects an engine for a given template. * * @author Fabien Potencier * * @api */ class DelegatingEngine implements EngineInterface, StreamingEngineInterface { /** * @var EngineInterface[] */ protected $engines = array(); /** * Constructor. * * @param EngineInterface[] $engines An array of EngineInterface instances to add * * @api */ public function __construct(array $engines = array()) { foreach ($engines as $engine) { $this->addEngine($engine); } } /** * {@inheritdoc} * * @api */ public function render($name, array $parameters = array()) { return $this->getEngine($name)->render($name, $parameters); } /** * {@inheritdoc} * * @api */ public function stream($name, array $parameters = array()) { $engine = $this->getEngine($name); if (!$engine instanceof StreamingEngineInterface) { throw new \LogicException(sprintf('Template "%s" cannot be streamed as the engine supporting it does not implement StreamingEngineInterface.', $name)); } $engine->stream($name, $parameters); } /** * {@inheritdoc} * * @api */ public function exists($name) { return $this->getEngine($name)->exists($name); } /** * Adds an engine. * * @param EngineInterface $engine An EngineInterface instance * * @api */ public function addEngine(EngineInterface $engine) { $this->engines[] = $engine; } /** * {@inheritdoc} * * @api */ public function supports($name) { try { $this->getEngine($name); } catch (\RuntimeException $e) { return false; } return true; } /** * Get an engine able to render the given template. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * * @return EngineInterface The engine * * @throws \RuntimeException if no engine able to work with the template is found * * @api */ public function getEngine($name) { foreach ($this->engines as $engine) { if ($engine->supports($name)) { return $engine; } } throw new \RuntimeException(sprintf('No engine is able to work with the template "%s".', $name)); } } PK]g((Templating/Loader/Loader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Loader; use Psr\Log\LoggerInterface; use Symfony\Component\Templating\DebuggerInterface; /** * Loader is the base class for all template loader classes. * * @author Fabien Potencier */ abstract class Loader implements LoaderInterface { /** * @var LoggerInterface|null */ protected $logger; /** * @deprecated Deprecated in 2.4, to be removed in 3.0. Use $this->logger instead. */ protected $debugger; /** * Sets the debug logger to use for this loader. * * @param LoggerInterface $logger A logger instance */ public function setLogger(LoggerInterface $logger) { $this->logger = $logger; } /** * Sets the debugger to use for this loader. * * @param DebuggerInterface $debugger A debugger instance * * @deprecated Deprecated in 2.4, to be removed in 3.0. Use $this->setLogger() instead. */ public function setDebugger(DebuggerInterface $debugger) { $this->debugger = $debugger; } } PK]>!Templating/Loader/ChainLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Loader; use Symfony\Component\Templating\Storage\Storage; use Symfony\Component\Templating\TemplateReferenceInterface; /** * ChainLoader is a loader that calls other loaders to load templates. * * @author Fabien Potencier */ class ChainLoader extends Loader { protected $loaders = array(); /** * Constructor. * * @param LoaderInterface[] $loaders An array of loader instances */ public function __construct(array $loaders = array()) { foreach ($loaders as $loader) { $this->addLoader($loader); } } /** * Adds a loader instance. * * @param LoaderInterface $loader A Loader instance */ public function addLoader(LoaderInterface $loader) { $this->loaders[] = $loader; } /** * Loads a template. * * @param TemplateReferenceInterface $template A template * * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise */ public function load(TemplateReferenceInterface $template) { foreach ($this->loaders as $loader) { if (false !== $storage = $loader->load($template)) { return $storage; } } return false; } /** * Returns true if the template is still fresh. * * @param TemplateReferenceInterface $template A template * @param integer $time The last modification time of the cached template (timestamp) * * @return Boolean */ public function isFresh(TemplateReferenceInterface $template, $time) { foreach ($this->loaders as $loader) { return $loader->isFresh($template, $time); } return false; } } PK]I * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Loader; use Symfony\Component\Templating\TemplateReferenceInterface; use Symfony\Component\Templating\Storage\Storage; /** * LoaderInterface is the interface all loaders must implement. * * @author Fabien Potencier * * @api */ interface LoaderInterface { /** * Loads a template. * * @param TemplateReferenceInterface $template A template * * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise * * @api */ public function load(TemplateReferenceInterface $template); /** * Returns true if the template is still fresh. * * @param TemplateReferenceInterface $template A template * @param integer $time The last modification time of the cached template (timestamp) * * @return Boolean * * @api */ public function isFresh(TemplateReferenceInterface $template, $time); } PK]yAn n !Templating/Loader/CacheLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Loader; use Symfony\Component\Templating\Storage\Storage; use Symfony\Component\Templating\Storage\FileStorage; use Symfony\Component\Templating\TemplateReferenceInterface; /** * CacheLoader is a loader that caches other loaders responses * on the filesystem. * * This cache only caches on disk to allow PHP accelerators to cache the opcodes. * All other mechanism would imply the use of `eval()`. * * @author Fabien Potencier */ class CacheLoader extends Loader { protected $loader; protected $dir; /** * Constructor. * * @param LoaderInterface $loader A Loader instance * @param string $dir The directory where to store the cache files */ public function __construct(LoaderInterface $loader, $dir) { $this->loader = $loader; $this->dir = $dir; } /** * Loads a template. * * @param TemplateReferenceInterface $template A template * * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise */ public function load(TemplateReferenceInterface $template) { $key = hash('sha256', $template->getLogicalName()); $dir = $this->dir.DIRECTORY_SEPARATOR.substr($key, 0, 2); $file = substr($key, 2).'.tpl'; $path = $dir.DIRECTORY_SEPARATOR.$file; if (is_file($path)) { if (null !== $this->logger) { $this->logger->debug(sprintf('Fetching template "%s" from cache', $template->get('name'))); } elseif (null !== $this->debugger) { // just for BC, to be removed in 3.0 $this->debugger->log(sprintf('Fetching template "%s" from cache', $template->get('name'))); } return new FileStorage($path); } if (false === $storage = $this->loader->load($template)) { return false; } $content = $storage->getContent(); if (!is_dir($dir)) { mkdir($dir, 0777, true); } file_put_contents($path, $content); if (null !== $this->logger) { $this->logger->debug(sprintf('Storing template "%s" in cache', $template->get('name'))); } elseif (null !== $this->debugger) { // just for BC, to be removed in 3.0 $this->debugger->log(sprintf('Storing template "%s" in cache', $template->get('name'))); } return new FileStorage($path); } /** * Returns true if the template is still fresh. * * @param TemplateReferenceInterface $template A template * @param integer $time The last modification time of the cached template (timestamp) * * @return Boolean */ public function isFresh(TemplateReferenceInterface $template, $time) { return $this->loader->isFresh($template, $time); } } PK]b&Templating/Loader/FilesystemLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Loader; use Symfony\Component\Templating\Storage\Storage; use Symfony\Component\Templating\Storage\FileStorage; use Symfony\Component\Templating\TemplateReferenceInterface; /** * FilesystemLoader is a loader that read templates from the filesystem. * * @author Fabien Potencier * * @api */ class FilesystemLoader extends Loader { protected $templatePathPatterns; /** * Constructor. * * @param array $templatePathPatterns An array of path patterns to look for templates * * @api */ public function __construct($templatePathPatterns) { $this->templatePathPatterns = (array) $templatePathPatterns; } /** * Loads a template. * * @param TemplateReferenceInterface $template A template * * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise * * @api */ public function load(TemplateReferenceInterface $template) { $file = $template->get('name'); if (self::isAbsolutePath($file) && is_file($file)) { return new FileStorage($file); } $replacements = array(); foreach ($template->all() as $key => $value) { $replacements['%'.$key.'%'] = $value; } $logs = array(); foreach ($this->templatePathPatterns as $templatePathPattern) { if (is_file($file = strtr($templatePathPattern, $replacements)) && is_readable($file)) { if (null !== $this->logger) { $this->logger->debug(sprintf('Loaded template file "%s"', $file)); } elseif (null !== $this->debugger) { // just for BC, to be removed in 3.0 $this->debugger->log(sprintf('Loaded template file "%s"', $file)); } return new FileStorage($file); } if (null !== $this->logger || null !== $this->debugger) { $logs[] = sprintf('Failed loading template file "%s"', $file); } } foreach ($logs as $log) { if (null !== $this->logger) { $this->logger->debug($log); } elseif (null !== $this->debugger) { $this->debugger->log($log); } } return false; } /** * Returns true if the template is still fresh. * * @param TemplateReferenceInterface $template A template * @param integer $time The last modification time of the cached template (timestamp) * * @return Boolean true if the template is still fresh, false otherwise * * @api */ public function isFresh(TemplateReferenceInterface $template, $time) { if (false === $storage = $this->load($template)) { return false; } return filemtime((string) $storage) < $time; } /** * Returns true if the file is an existing absolute path. * * @param string $file A path * * @return Boolean true if the path exists and is absolute, false otherwise */ protected static function isAbsolutePath($file) { if ($file[0] == '/' || $file[0] == '\\' || (strlen($file) > 3 && ctype_alpha($file[0]) && $file[1] == ':' && ($file[2] == '\\' || $file[2] == '/') ) || null !== parse_url($file, PHP_URL_SCHEME) ) { return true; } return false; } } PK]DZ_++*Templating/TemplateNameParserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * TemplateNameParserInterface converts template names to TemplateReferenceInterface * instances. * * @author Fabien Potencier * * @api */ interface TemplateNameParserInterface { /** * Convert a template name to a TemplateReferenceInterface instance. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * * @return TemplateReferenceInterface A template * * @api */ public function parse($name); } PK]!Templating/TemplateNameParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * TemplateNameParser is the default implementation of TemplateNameParserInterface. * * This implementation takes everything as the template name * and the extension for the engine. * * @author Fabien Potencier * * @api */ class TemplateNameParser implements TemplateNameParserInterface { /** * {@inheritdoc} * * @api */ public function parse($name) { if ($name instanceof TemplateReferenceInterface) { return $name; } $engine = null; if (false !== $pos = strrpos($name, '.')) { $engine = substr($name, $pos + 1); } return new TemplateReference($name, $engine); } } PK])Templating/TemplateReferenceInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * Interface to be implemented by all templates. * * @author Victor Berchet * * @api */ interface TemplateReferenceInterface { /** * Gets the template parameters. * * @return array An array of parameters * * @api */ public function all(); /** * Sets a template parameter. * * @param string $name The parameter name * @param string $value The parameter value * * @return TemplateReferenceInterface The TemplateReferenceInterface instance * * @throws \InvalidArgumentException if the parameter name is not supported * * @api */ public function set($name, $value); /** * Gets a template parameter. * * @param string $name The parameter name * * @return string The parameter value * * @throws \InvalidArgumentException if the parameter name is not supported * * @api */ public function get($name); /** * Returns the path to the template. * * By default, it just returns the template name. * * @return string A path to the template or a resource * * @api */ public function getPath(); /** * Returns the "logical" template name. * * The template name acts as a unique identifier for the template. * * @return string The template name * * @api */ public function getLogicalName(); /** * Returns the string representation as shortcut for getLogicalName(). * * Alias of getLogicalName(). * * @return string The template name * * @api */ public function __toString(); } PK]J  Templating/DebuggerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * DebuggerInterface is the interface you need to implement * to debug template loader instances. * * @author Fabien Potencier * * @deprecated Deprecated in 2.4, to be removed in 3.0. Use Psr\Log\LoggerInterface instead. */ interface DebuggerInterface { /** * Logs a message. * * @param string $message A message to log */ public function log($message); } PK]mtTTTemplating/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * Internal representation of a template. * * @author Victor Berchet * * @api */ class TemplateReference implements TemplateReferenceInterface { protected $parameters; public function __construct($name = null, $engine = null) { $this->parameters = array( 'name' => $name, 'engine' => $engine, ); } /** * {@inheritdoc} */ public function __toString() { return $this->getLogicalName(); } /** * {@inheritdoc} * * @api */ public function set($name, $value) { if (array_key_exists($name, $this->parameters)) { $this->parameters[$name] = $value; } else { throw new \InvalidArgumentException(sprintf('The template does not support the "%s" parameter.', $name)); } return $this; } /** * {@inheritdoc} * * @api */ public function get($name) { if (array_key_exists($name, $this->parameters)) { return $this->parameters[$name]; } throw new \InvalidArgumentException(sprintf('The template does not support the "%s" parameter.', $name)); } /** * {@inheritdoc} * * @api */ public function all() { return $this->parameters; } /** * {@inheritdoc} * * @api */ public function getPath() { return $this->parameters['name']; } /** * {@inheritdoc} * * @api */ public function getLogicalName() { return $this->parameters['name']; } } PK]s s HttpKernel/KernelEvents.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; /** * Contains all events thrown in the HttpKernel component * * @author Bernhard Schussek * * @api */ final class KernelEvents { /** * The REQUEST event occurs at the very beginning of request * dispatching * * This event allows you to create a response for a request before any * other code in the framework is executed. The event listener method * receives a Symfony\Component\HttpKernel\Event\GetResponseEvent * instance. * * @var string * * @api */ const REQUEST = 'kernel.request'; /** * The EXCEPTION event occurs when an uncaught exception appears * * This event allows you to create a response for a thrown exception or * to modify the thrown exception. The event listener method receives * a Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent * instance. * * @var string * * @api */ const EXCEPTION = 'kernel.exception'; /** * The VIEW event occurs when the return value of a controller * is not a Response instance * * This event allows you to create a response for the return value of the * controller. The event listener method receives a * Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent * instance. * * @var string * * @api */ const VIEW = 'kernel.view'; /** * The CONTROLLER event occurs once a controller was found for * handling a request * * This event allows you to change the controller that will handle the * request. The event listener method receives a * Symfony\Component\HttpKernel\Event\FilterControllerEvent instance. * * @var string * * @api */ const CONTROLLER = 'kernel.controller'; /** * The RESPONSE event occurs once a response was created for * replying to a request * * This event allows you to modify or replace the response that will be * replied. The event listener method receives a * Symfony\Component\HttpKernel\Event\FilterResponseEvent instance. * * @var string * * @api */ const RESPONSE = 'kernel.response'; /** * The TERMINATE event occurs once a response was sent * * This event allows you to run expensive post-response jobs. * The event listener method receives a * Symfony\Component\HttpKernel\Event\PostResponseEvent instance. * * @var string */ const TERMINATE = 'kernel.terminate'; /** * The REQUEST_FINISHED event occurs when a response was generated for a request. * * This event allows you to reset the global and environmental state of * the application, when it was changed during the request. * * @var string */ const FINISH_REQUEST = 'kernel.finish_request'; } PK]kt$$HttpKernel/HttpKernel.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Event\PostResponseEvent; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * HttpKernel notifies events to convert a Request object to a Response one. * * @author Fabien Potencier * * @api */ class HttpKernel implements HttpKernelInterface, TerminableInterface { protected $dispatcher; protected $resolver; protected $requestStack; /** * Constructor * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance * @param RequestStack $requestStack A stack for master/sub requests * * @api */ public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null) { $this->dispatcher = $dispatcher; $this->resolver = $resolver; $this->requestStack = $requestStack ?: new RequestStack(); } /** * {@inheritdoc} * * @api */ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { try { return $this->handleRaw($request, $type); } catch (\Exception $e) { if (false === $catch) { $this->finishRequest($request, $type); throw $e; } return $this->handleException($e, $request, $type); } } /** * {@inheritdoc} * * @api */ public function terminate(Request $request, Response $response) { $this->dispatcher->dispatch(KernelEvents::TERMINATE, new PostResponseEvent($this, $request, $response)); } /** * Handles a request to convert it to a response. * * Exceptions are not caught. * * @param Request $request A Request instance * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) * * @return Response A Response instance * * @throws \LogicException If one of the listener does not behave as expected * @throws NotFoundHttpException When controller cannot be found */ private function handleRaw(Request $request, $type = self::MASTER_REQUEST) { $this->requestStack->push($request); // request $event = new GetResponseEvent($this, $request, $type); $this->dispatcher->dispatch(KernelEvents::REQUEST, $event); if ($event->hasResponse()) { return $this->filterResponse($event->getResponse(), $request, $type); } // load controller if (false === $controller = $this->resolver->getController($request)) { throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". Maybe you forgot to add the matching route in your routing configuration?', $request->getPathInfo())); } $event = new FilterControllerEvent($this, $controller, $request, $type); $this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event); $controller = $event->getController(); // controller arguments $arguments = $this->resolver->getArguments($request, $controller); // call controller $response = call_user_func_array($controller, $arguments); // view if (!$response instanceof Response) { $event = new GetResponseForControllerResultEvent($this, $request, $type, $response); $this->dispatcher->dispatch(KernelEvents::VIEW, $event); if ($event->hasResponse()) { $response = $event->getResponse(); } if (!$response instanceof Response) { $msg = sprintf('The controller must return a response (%s given).', $this->varToString($response)); // the user may have forgotten to return something if (null === $response) { $msg .= ' Did you forget to add a return statement somewhere in your controller?'; } throw new \LogicException($msg); } } return $this->filterResponse($response, $request, $type); } /** * Filters a response object. * * @param Response $response A Response instance * @param Request $request An error message in case the response is not a Response object * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) * * @return Response The filtered Response instance * * @throws \RuntimeException if the passed object is not a Response instance */ private function filterResponse(Response $response, Request $request, $type) { $event = new FilterResponseEvent($this, $request, $type, $response); $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); $this->finishRequest($request, $type); return $event->getResponse(); } /** * Publishes the finish request event, then pop the request from the stack. * * Note that the order of the operations is important here, otherwise * operations such as {@link RequestStack::getParentRequest()} can lead to * weird results. * * @param Request $request * @param int $type */ private function finishRequest(Request $request, $type) { $this->dispatcher->dispatch(KernelEvents::FINISH_REQUEST, new FinishRequestEvent($this, $request, $type)); $this->requestStack->pop(); } /** * Handles an exception by trying to convert it to a Response. * * @param \Exception $e An \Exception instance * @param Request $request A Request instance * @param integer $type The type of the request * * @return Response A Response instance * * @throws \Exception */ private function handleException(\Exception $e, $request, $type) { $event = new GetResponseForExceptionEvent($this, $request, $type, $e); $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event); // a listener might have replaced the exception $e = $event->getException(); if (!$event->hasResponse()) { $this->finishRequest($request, $type); throw $e; } $response = $event->getResponse(); // the developer asked for a specific status code if ($response->headers->has('X-Status-Code')) { $response->setStatusCode($response->headers->get('X-Status-Code')); $response->headers->remove('X-Status-Code'); } elseif (!$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { // ensure that we actually have an error response if ($e instanceof HttpExceptionInterface) { // keep the HTTP status code and headers $response->setStatusCode($e->getStatusCode()); $response->headers->add($e->getHeaders()); } else { $response->setStatusCode(500); } } try { return $this->filterResponse($response, $request, $type); } catch (\Exception $e) { return $response; } } private function varToString($var) { if (is_object($var)) { return sprintf('Object(%s)', get_class($var)); } if (is_array($var)) { $a = array(); foreach ($var as $k => $v) { $a[] = sprintf('%s => %s', $k, $this->varToString($v)); } return sprintf("Array(%s)", implode(', ', $a)); } if (is_resource($var)) { return sprintf('Resource(%s)', get_resource_type($var)); } if (null === $var) { return 'null'; } if (false === $var) { return 'false'; } if (true === $var) { return 'true'; } return (string) $var; } } PK]^t"HttpKernel/TerminableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Terminable extends the Kernel request/response cycle with dispatching a post * response event after sending the response and before shutting down the kernel. * * @author Jordi Boggiano * @author Pierre Minnieur * * @api */ interface TerminableInterface { /** * Terminates a request/response cycle. * * Should be called after sending the response and before shutting down the kernel. * * @param Request $request A Request instance * @param Response $response A Response instance * * @api */ public function terminate(Request $request, Response $response); } PK]><HttpKernel/Log/NullLogger.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Log; use Psr\Log\NullLogger as PsrNullLogger; /** * NullLogger. * * @author Fabien Potencier * * @api */ class NullLogger extends PsrNullLogger implements LoggerInterface { /** * @api * @deprecated since 2.2, to be removed in 3.0. Use emergency() which is PSR-3 compatible. */ public function emerg($message, array $context = array()) { } /** * @api * @deprecated since 2.2, to be removed in 3.0. Use critical() which is PSR-3 compatible. */ public function crit($message, array $context = array()) { } /** * @api * @deprecated since 2.2, to be removed in 3.0. Use error() which is PSR-3 compatible. */ public function err($message, array $context = array()) { } /** * @api * @deprecated since 2.2, to be removed in 3.0. Use warning() which is PSR-3 compatible. */ public function warn($message, array $context = array()) { } } PK]J=[['HttpKernel/Log/DebugLoggerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Log; /** * DebugLoggerInterface. * * @author Fabien Potencier */ interface DebugLoggerInterface { /** * Returns an array of logs. * * A log is an array with the following mandatory keys: * timestamp, message, priority, and priorityName. * It can also have an optional context key containing an array. * * @return array An array of logs */ public function getLogs(); /** * Returns the number of errors. * * @return integer The number of errors */ public function countErrors(); } PK]~[  "HttpKernel/Log/LoggerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Log; use Psr\Log\LoggerInterface as PsrLogger; /** * LoggerInterface. * * @author Fabien Potencier * * @deprecated since 2.2, to be removed in 3.0. Type-hint \Psr\Log\LoggerInterface instead. * @api */ interface LoggerInterface extends PsrLogger { /** * @api * @deprecated since 2.2, to be removed in 3.0. Use emergency() which is PSR-3 compatible. */ public function emerg($message, array $context = array()); /** * @api * @deprecated since 2.2, to be removed in 3.0. Use critical() which is PSR-3 compatible. */ public function crit($message, array $context = array()); /** * @api * @deprecated since 2.2, to be removed in 3.0. Use error() which is PSR-3 compatible. */ public function err($message, array $context = array()); /** * @api * @deprecated since 2.2, to be removed in 3.0. Use warning() which is PSR-3 compatible. */ public function warn($message, array $context = array()); } PK]=AA"HttpKernel/HttpKernelInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * HttpKernelInterface handles a Request to convert it to a Response. * * @author Fabien Potencier * * @api */ interface HttpKernelInterface { const MASTER_REQUEST = 1; const SUB_REQUEST = 2; /** * Handles a Request to convert it to a Response. * * When $catch is true, the implementation must catch all exceptions * and do its best to convert them to a Response instance. * * @param Request $request A Request instance * @param integer $type The type of the request * (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) * @param Boolean $catch Whether to catch exceptions or not * * @return Response A Response instance * * @throws \Exception When an Exception occurs during processing * * @api */ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true); } PK];M,HttpKernel/DependencyInjection/Extension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension; /** * Allow adding classes to the class cache. * * @author Fabien Potencier */ abstract class Extension extends BaseExtension { private $classes = array(); /** * Gets the classes to cache. * * @return array An array of classes */ public function getClassesToCompile() { return $this->classes; } /** * Adds classes to the class cache. * * @param array $classes An array of classes */ public function addClassesToCompile(array $classes) { $this->classes = array_merge($this->classes, $classes); } } PK]&!#ffBHttpKernel/DependencyInjection/MergeExtensionConfigurationPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass as BaseMergeExtensionConfigurationPass; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Ensures certain extensions are always loaded. * * @author Kris Wallsmith */ class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPass { private $extensions; public function __construct(array $extensions) { $this->extensions = $extensions; } public function process(ContainerBuilder $container) { foreach ($this->extensions as $extension) { if (!count($container->getExtensionConfig($extension))) { $container->loadFromExtension($extension, array()); } } parent::process($container); } } PK]u__8HttpKernel/DependencyInjection/ConfigurableExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * This extension sub-class provides first-class integration with the * Config/Definition Component. * * You can use this as base class if you * * a) use the Config/Definition component for configuration * b) your configuration class is named "Configuration" and * c) the configuration class resides in the DependencyInjection sub-folder * * @author Johannes M. Schmitt */ abstract class ConfigurableExtension extends Extension { /** * {@inheritDoc} */ final public function load(array $configs, ContainerBuilder $container) { $this->loadInternal($this->processConfiguration($this->getConfiguration($configs, $container), $configs), $container); } /** * Configures the passed container according to the merged configuration. * * @param array $mergedConfig * @param ContainerBuilder $container */ abstract protected function loadInternal(array $mergedConfig, ContainerBuilder $container); } PK]k8HttpKernel/DependencyInjection/RegisterListenersPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; /** * Compiler pass to register tagged services for an event dispatcher. */ class RegisterListenersPass implements CompilerPassInterface { /** * @var string */ protected $dispatcherService; /** * @var string */ protected $listenerTag; /** * @var string */ protected $subscriberTag; /** * Constructor. * * @param string $dispatcherService Service name of the event dispatcher in processed container * @param string $listenerTag Tag name used for listener * @param string $subscriberTag Tag name used for subscribers */ public function __construct($dispatcherService = 'event_dispatcher', $listenerTag = 'kernel.event_listener', $subscriberTag = 'kernel.event_subscriber') { $this->dispatcherService = $dispatcherService; $this->listenerTag = $listenerTag; $this->subscriberTag = $subscriberTag; } public function process(ContainerBuilder $container) { if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) { return; } $definition = $container->findDefinition($this->dispatcherService); foreach ($container->findTaggedServiceIds($this->listenerTag) as $id => $events) { $def = $container->getDefinition($id); if (!$def->isPublic()) { throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event listeners are lazy-loaded.', $id)); } if ($def->isAbstract()) { throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event listeners are lazy-loaded.', $id)); } foreach ($events as $event) { $priority = isset($event['priority']) ? $event['priority'] : 0; if (!isset($event['event'])) { throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); } if (!isset($event['method'])) { $event['method'] = 'on'.preg_replace_callback(array( '/(?<=\b)[a-z]/i', '/[^a-z0-9]/i', ), function ($matches) { return strtoupper($matches[0]); }, $event['event']); $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); } $definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority)); } } foreach ($container->findTaggedServiceIds($this->subscriberTag) as $id => $attributes) { $def = $container->getDefinition($id); if (!$def->isPublic()) { throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id)); } // We must assume that the class value has been correctly filled, even if the service is created by a factory $class = $def->getClass(); $refClass = new \ReflectionClass($class); $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; if (!$refClass->implementsInterface($interface)) { throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); } $definition->addMethodCall('addSubscriberService', array($id, $class)); } } } PK]QNR8HttpKernel/DependencyInjection/AddClassesToCachePass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\HttpKernel\Kernel; /** * Sets the classes to compile in the cache for the container. * * @author Fabien Potencier */ class AddClassesToCachePass implements CompilerPassInterface { private $kernel; public function __construct(Kernel $kernel) { $this->kernel = $kernel; } /** * {@inheritDoc} */ public function process(ContainerBuilder $container) { $classes = array(); foreach ($container->getExtensions() as $extension) { if ($extension instanceof Extension) { $classes = array_merge($classes, $extension->getClassesToCompile()); } } $this->kernel->setClassCache(array_unique($container->getParameterBag()->resolveValue($classes))); } } PK]6V V ;HttpKernel/DependencyInjection/ContainerAwareHttpKernel.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Scope; /** * Adds a managed request scope. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class ContainerAwareHttpKernel extends HttpKernel { protected $container; /** * Constructor. * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param ContainerInterface $container A ContainerInterface instance * @param ControllerResolverInterface $controllerResolver A ControllerResolverInterface instance * @param RequestStack $requestStack A stack for master/sub requests */ public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver, RequestStack $requestStack = null) { parent::__construct($dispatcher, $controllerResolver, $requestStack); $this->container = $container; // the request scope might have been created before (see FrameworkBundle) if (!$container->hasScope('request')) { $container->addScope(new Scope('request')); } } /** * {@inheritdoc} */ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { $request->headers->set('X-Php-Ob-Level', ob_get_level()); $this->container->enterScope('request'); $this->container->set('request', $request, 'request'); try { $response = parent::handle($request, $type, $catch); } catch (\Exception $e) { $this->container->set('request', null, 'request'); $this->container->leaveScope('request'); throw $e; } $this->container->set('request', null, 'request'); $this->container->leaveScope('request'); return $response; } } PK]Yxځ551HttpKernel/CacheClearer/CacheClearerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheClearer; /** * CacheClearerInterface. * * @author Dustin Dobervich */ interface CacheClearerInterface { /** * Clears any caches necessary. * * @param string $cacheDir The cache directory. */ public function clear($cacheDir); } PK]-HttpKernel/CacheClearer/ChainCacheClearer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheClearer; /** * ChainCacheClearer. * * @author Dustin Dobervich */ class ChainCacheClearer implements CacheClearerInterface { /** * @var array $clearers */ protected $clearers; /** * Constructs a new instance of ChainCacheClearer. * * @param array $clearers The initial clearers. */ public function __construct(array $clearers = array()) { $this->clearers = $clearers; } /** * {@inheritDoc} */ public function clear($cacheDir) { foreach ($this->clearers as $clearer) { $clearer->clear($cacheDir); } } /** * Adds a cache clearer to the aggregate. * * @param CacheClearerInterface $clearer */ public function add(CacheClearerInterface $clearer) { $this->clearers[] = $clearer; } } PK]2~~0HttpKernel/DataCollector/ConfigDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * ConfigDataCollector. * * @author Fabien Potencier */ class ConfigDataCollector extends DataCollector { private $kernel; private $name; private $version; /** * Constructor. * * @param string $name The name of the application using the web profiler * @param string $version The version of the application using the web profiler */ public function __construct($name = null, $version = null) { $this->name = $name; $this->version = $version; } /** * Sets the Kernel associated with this Request. * * @param KernelInterface $kernel A KernelInterface instance */ public function setKernel(KernelInterface $kernel = null) { $this->kernel = $kernel; } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { $this->data = array( 'app_name' => $this->name, 'app_version' => $this->version, 'token' => $response->headers->get('X-Debug-Token'), 'symfony_version' => Kernel::VERSION, 'name' => isset($this->kernel) ? $this->kernel->getName() : 'n/a', 'env' => isset($this->kernel) ? $this->kernel->getEnvironment() : 'n/a', 'debug' => isset($this->kernel) ? $this->kernel->isDebug() : 'n/a', 'php_version' => PHP_VERSION, 'xdebug_enabled' => extension_loaded('xdebug'), 'eaccel_enabled' => extension_loaded('eaccelerator') && ini_get('eaccelerator.enable'), 'apc_enabled' => extension_loaded('apc') && ini_get('apc.enabled'), 'xcache_enabled' => extension_loaded('xcache') && ini_get('xcache.cacher'), 'wincache_enabled' => extension_loaded('wincache') && ini_get('wincache.ocenabled'), 'zend_opcache_enabled' => extension_loaded('Zend OPcache') && ini_get('opcache.enable'), 'bundles' => array(), 'sapi_name' => php_sapi_name() ); if (isset($this->kernel)) { foreach ($this->kernel->getBundles() as $name => $bundle) { $this->data['bundles'][$name] = $bundle->getPath(); } } } public function getApplicationName() { return $this->data['app_name']; } public function getApplicationVersion() { return $this->data['app_version']; } /** * Gets the token. * * @return string The token */ public function getToken() { return $this->data['token']; } /** * Gets the Symfony version. * * @return string The Symfony version */ public function getSymfonyVersion() { return $this->data['symfony_version']; } /** * Gets the PHP version. * * @return string The PHP version */ public function getPhpVersion() { return $this->data['php_version']; } /** * Gets the application name. * * @return string The application name */ public function getAppName() { return $this->data['name']; } /** * Gets the environment. * * @return string The environment */ public function getEnv() { return $this->data['env']; } /** * Returns true if the debug is enabled. * * @return Boolean true if debug is enabled, false otherwise */ public function isDebug() { return $this->data['debug']; } /** * Returns true if the XDebug is enabled. * * @return Boolean true if XDebug is enabled, false otherwise */ public function hasXDebug() { return $this->data['xdebug_enabled']; } /** * Returns true if EAccelerator is enabled. * * @return Boolean true if EAccelerator is enabled, false otherwise */ public function hasEAccelerator() { return $this->data['eaccel_enabled']; } /** * Returns true if APC is enabled. * * @return Boolean true if APC is enabled, false otherwise */ public function hasApc() { return $this->data['apc_enabled']; } /** * Returns true if Zend OPcache is enabled * * @return Boolean true if Zend OPcache is enabled, false otherwise */ public function hasZendOpcache() { return $this->data['zend_opcache_enabled']; } /** * Returns true if XCache is enabled. * * @return Boolean true if XCache is enabled, false otherwise */ public function hasXCache() { return $this->data['xcache_enabled']; } /** * Returns true if WinCache is enabled. * * @return Boolean true if WinCache is enabled, false otherwise */ public function hasWinCache() { return $this->data['wincache_enabled']; } /** * Returns true if any accelerator is enabled. * * @return Boolean true if any accelerator is enabled, false otherwise */ public function hasAccelerator() { return $this->hasApc() || $this->hasZendOpcache() || $this->hasEAccelerator() || $this->hasXCache() || $this->hasWinCache(); } public function getBundles() { return $this->data['bundles']; } /** * Gets the PHP SAPI name. * * @return string The environment */ public function getSapiName() { return $this->data['sapi_name']; } /** * {@inheritdoc} */ public function getName() { return 'config'; } } PK](; ; 0HttpKernel/DataCollector/MemoryDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * MemoryDataCollector. * * @author Fabien Potencier */ class MemoryDataCollector extends DataCollector implements LateDataCollectorInterface { public function __construct() { $this->data = array( 'memory' => 0, 'memory_limit' => $this->convertToBytes(ini_get('memory_limit')), ); } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { $this->updateMemoryUsage(); } /** * {@inheritdoc} */ public function lateCollect() { $this->updateMemoryUsage(); } /** * Gets the memory. * * @return integer The memory */ public function getMemory() { return $this->data['memory']; } /** * Gets the PHP memory limit. * * @return integer The memory limit */ public function getMemoryLimit() { return $this->data['memory_limit']; } /** * Updates the memory usage data. */ public function updateMemoryUsage() { $this->data['memory'] = memory_get_peak_usage(true); } /** * {@inheritdoc} */ public function getName() { return 'memory'; } private function convertToBytes($memoryLimit) { if ('-1' === $memoryLimit) { return -1; } $memoryLimit = strtolower($memoryLimit); $max = strtolower(ltrim($memoryLimit, '+')); if (0 === strpos($max, '0x')) { $max = intval($max, 16); } elseif (0 === strpos($max, '0')) { $max = intval($max, 8); } else { $max = intval($max); } switch (substr($memoryLimit, -1)) { case 't': $max *= 1024; case 'g': $max *= 1024; case 'm': $max *= 1024; case 'k': $max *= 1024; } return $max; } } PK].3HttpKernel/DataCollector/DataCollectorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * DataCollectorInterface. * * @author Fabien Potencier * * @api */ interface DataCollectorInterface { /** * Collects data for the given Request and Response. * * @param Request $request A Request instance * @param Response $response A Response instance * @param \Exception $exception An Exception instance * * @api */ public function collect(Request $request, Response $response, \Exception $exception = null); /** * Returns the name of the collector. * * @return string The collector name * * @api */ public function getName(); } PK]@:o o 0HttpKernel/DataCollector/RouterDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; /** * RouterDataCollector. * * @author Fabien Potencier */ class RouterDataCollector extends DataCollector { protected $controllers; public function __construct() { $this->controllers = new \SplObjectStorage(); $this->data = array( 'redirect' => false, 'url' => null, 'route' => null, ); } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { if ($response instanceof RedirectResponse) { $this->data['redirect'] = true; $this->data['url'] = $response->getTargetUrl(); if ($this->controllers->contains($request)) { $this->data['route'] = $this->guessRoute($request, $this->controllers[$request]); } } unset($this->controllers[$request]); } protected function guessRoute(Request $request, $controller) { return 'n/a'; } /** * Remembers the controller associated to each request. * * @param FilterControllerEvent $event The filter controller event */ public function onKernelController(FilterControllerEvent $event) { $this->controllers[$event->getRequest()] = $event->getController(); } /** * @return Boolean Whether this request will result in a redirect */ public function getRedirect() { return $this->data['redirect']; } /** * @return string|null The target URL */ public function getTargetUrl() { return $this->data['url']; } /** * @return string|null The target route */ public function getTargetRoute() { return $this->data['route']; } /** * {@inheritdoc} */ public function getName() { return 'router'; } } PK] <7HttpKernel/DataCollector/LateDataCollectorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; /** * LateDataCollectorInterface. * * @author Fabien Potencier */ interface LateDataCollectorInterface { /** * Collects data as late as possible. */ public function lateCollect(); } PK]޹ 0HttpKernel/DataCollector/LoggerDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Debug\ErrorHandler; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; /** * LogDataCollector. * * @author Fabien Potencier */ class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface { private $logger; public function __construct($logger = null) { if (null !== $logger && $logger instanceof DebugLoggerInterface) { $this->logger = $logger; } } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { // everything is done as late as possible } /** * {@inheritdoc} */ public function lateCollect() { if (null !== $this->logger) { $this->data = array( 'error_count' => $this->logger->countErrors(), 'logs' => $this->sanitizeLogs($this->logger->getLogs()), 'deprecation_count' => $this->computeDeprecationCount() ); } } /** * Gets the called events. * * @return array An array of called events * * @see TraceableEventDispatcherInterface */ public function countErrors() { return isset($this->data['error_count']) ? $this->data['error_count'] : 0; } /** * Gets the logs. * * @return array An array of logs */ public function getLogs() { return isset($this->data['logs']) ? $this->data['logs'] : array(); } public function countDeprecations() { return isset($this->data['deprecation_count']) ? $this->data['deprecation_count'] : 0; } /** * {@inheritdoc} */ public function getName() { return 'logger'; } private function sanitizeLogs($logs) { foreach ($logs as $i => $log) { $logs[$i]['context'] = $this->sanitizeContext($log['context']); } return $logs; } private function sanitizeContext($context) { if (is_array($context)) { foreach ($context as $key => $value) { $context[$key] = $this->sanitizeContext($value); } return $context; } if (is_resource($context)) { return sprintf('Resource(%s)', get_resource_type($context)); } if (is_object($context)) { return sprintf('Object(%s)', get_class($context)); } return $context; } private function computeDeprecationCount() { $count = 0; foreach ($this->logger->getLogs() as $log) { if (isset($log['context']['type']) && ErrorHandler::TYPE_DEPRECATION === $log['context']['type']) { $count++; } } return $count; } } PK] /HttpKernel/DataCollector/EventDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; /** * EventDataCollector. * * @author Fabien Potencier */ class EventDataCollector extends DataCollector implements LateDataCollectorInterface { protected $dispatcher; public function __construct(EventDispatcherInterface $dispatcher = null) { $this->dispatcher = $dispatcher; } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { $this->data = array( 'called_listeners' => array(), 'not_called_listeners' => array(), ); } public function lateCollect() { if ($this->dispatcher instanceof TraceableEventDispatcherInterface) { $this->setCalledListeners($this->dispatcher->getCalledListeners()); $this->setNotCalledListeners($this->dispatcher->getNotCalledListeners()); } } /** * Sets the called listeners. * * @param array $listeners An array of called listeners * * @see TraceableEventDispatcherInterface */ public function setCalledListeners(array $listeners) { $this->data['called_listeners'] = $listeners; } /** * Gets the called listeners. * * @return array An array of called listeners * * @see TraceableEventDispatcherInterface */ public function getCalledListeners() { return $this->data['called_listeners']; } /** * Sets the not called listeners. * * @param array $listeners An array of not called listeners * * @see TraceableEventDispatcherInterface */ public function setNotCalledListeners(array $listeners) { $this->data['not_called_listeners'] = $listeners; } /** * Gets the not called listeners. * * @return array An array of not called listeners * * @see TraceableEventDispatcherInterface */ public function getNotCalledListeners() { return $this->data['not_called_listeners']; } /** * {@inheritdoc} */ public function getName() { return 'events'; } } PK]83HttpKernel/DataCollector/ExceptionDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\FlattenException; /** * ExceptionDataCollector. * * @author Fabien Potencier */ class ExceptionDataCollector extends DataCollector { /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { if (null !== $exception) { $this->data = array( 'exception' => FlattenException::create($exception), ); } } /** * Checks if the exception is not null. * * @return Boolean true if the exception is not null, false otherwise */ public function hasException() { return isset($this->data['exception']); } /** * Gets the exception. * * @return \Exception The exception */ public function getException() { return $this->data['exception']; } /** * Gets the exception message. * * @return string The exception message */ public function getMessage() { return $this->data['exception']->getMessage(); } /** * Gets the exception code. * * @return integer The exception code */ public function getCode() { return $this->data['exception']->getCode(); } /** * Gets the status code. * * @return integer The status code */ public function getStatusCode() { return $this->data['exception']->getStatusCode(); } /** * Gets the exception trace. * * @return array The exception trace */ public function getTrace() { return $this->data['exception']->getTrace(); } /** * {@inheritdoc} */ public function getName() { return 'exception'; } } PK]ƏGV .HttpKernel/DataCollector/TimeDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\KernelInterface; /** * TimeDataCollector. * * @author Fabien Potencier */ class TimeDataCollector extends DataCollector implements LateDataCollectorInterface { protected $kernel; protected $stopwatch; public function __construct(KernelInterface $kernel = null, $stopwatch = null) { $this->kernel = $kernel; $this->stopwatch = $stopwatch; } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { if (null !== $this->kernel) { $startTime = $this->kernel->getStartTime(); } else { $startTime = $request->server->get('REQUEST_TIME_FLOAT', $request->server->get('REQUEST_TIME')); } $this->data = array( 'token' => $response->headers->get('X-Debug-Token'), 'start_time' => $startTime * 1000, 'events' => array(), ); } /** * {@inheritdoc} */ public function lateCollect() { if (null !== $this->stopwatch && isset($this->data['token'])) { $this->setEvents($this->stopwatch->getSectionEvents($this->data['token'])); } unset($this->data['token']); } /** * Sets the request events. * * @param array $events The request events */ public function setEvents(array $events) { foreach ($events as $event) { $event->ensureStopped(); } $this->data['events'] = $events; } /** * Gets the request events. * * @return array The request events */ public function getEvents() { return $this->data['events']; } /** * Gets the request elapsed time. * * @return float The elapsed time */ public function getDuration() { if (!isset($this->data['events']['__section__'])) { return 0; } $lastEvent = $this->data['events']['__section__']; return $lastEvent->getOrigin() + $lastEvent->getDuration() - $this->getStartTime(); } /** * Gets the initialization time. * * This is the time spent until the beginning of the request handling. * * @return float The elapsed time */ public function getInitTime() { if (!isset($this->data['events']['__section__'])) { return 0; } return $this->data['events']['__section__']->getOrigin() - $this->getStartTime(); } /** * Gets the request time. * * @return integer The time */ public function getStartTime() { return $this->data['start_time']; } /** * {@inheritdoc} */ public function getName() { return 'time'; } } PK] +66/HttpKernel/DataCollector/Util/ValueExporter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector\Util; /** * @author Bernhard Schussek */ class ValueExporter { /** * Converts a PHP value to a string. * * @param mixed $value The PHP value * * @return string The string representation of the given value */ public function exportValue($value) { if (is_object($value)) { return sprintf('Object(%s)', get_class($value)); } if (is_array($value)) { $a = array(); foreach ($value as $k => $v) { $a[] = sprintf('%s => %s', $k, $this->exportValue($v)); } return sprintf("Array(%s)", implode(', ', $a)); } if (is_resource($value)) { return sprintf('Resource(%s)', get_resource_type($value)); } if (null === $value) { return 'null'; } if (false === $value) { return 'false'; } if (true === $value) { return 'true'; } return (string) $value; } } PK]n--*HttpKernel/DataCollector/DataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; /** * DataCollector. * * Children of this class must store the collected data in the data property. * * @author Fabien Potencier * @author Bernhard Schussek */ abstract class DataCollector implements DataCollectorInterface, \Serializable { protected $data; /** * @var ValueExporter */ private $valueExporter; public function serialize() { return serialize($this->data); } public function unserialize($data) { $this->data = unserialize($data); } /** * Converts a PHP variable to a string. * * @param mixed $var A PHP variable * * @return string The string representation of the variable */ protected function varToString($var) { if (null === $this->valueExporter) { $this->valueExporter = new ValueExporter(); } return $this->valueExporter->exportValue($var); } } PK]IYz((1HttpKernel/DataCollector/RequestDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\HeaderBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * RequestDataCollector. * * @author Fabien Potencier */ class RequestDataCollector extends DataCollector implements EventSubscriberInterface { protected $controllers; public function __construct() { $this->controllers = new \SplObjectStorage(); } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { $responseHeaders = $response->headers->all(); $cookies = array(); foreach ($response->headers->getCookies() as $cookie) { $cookies[] = $this->getCookieHeader($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); } if (count($cookies) > 0) { $responseHeaders['Set-Cookie'] = $cookies; } $attributes = array(); foreach ($request->attributes->all() as $key => $value) { if ('_route' === $key && is_object($value)) { $attributes['_route'] = $this->varToString($value->getPath()); } elseif ('_route_params' === $key) { foreach ($value as $key => $v) { $attributes['_route_params'][$key] = $this->varToString($v); } } else { $attributes[$key] = $this->varToString($value); } } $content = null; try { $content = $request->getContent(); } catch (\LogicException $e) { // the user already got the request content as a resource $content = false; } $sessionMetadata = array(); $sessionAttributes = array(); $flashes = array(); if ($request->hasSession()) { $session = $request->getSession(); if ($session->isStarted()) { $sessionMetadata['Created'] = date(DATE_RFC822, $session->getMetadataBag()->getCreated()); $sessionMetadata['Last used'] = date(DATE_RFC822, $session->getMetadataBag()->getLastUsed()); $sessionMetadata['Lifetime'] = $session->getMetadataBag()->getLifetime(); $sessionAttributes = $session->all(); $flashes = $session->getFlashBag()->peekAll(); } } $statusCode = $response->getStatusCode(); $this->data = array( 'format' => $request->getRequestFormat(), 'content' => $content, 'content_type' => $response->headers->get('Content-Type') ? $response->headers->get('Content-Type') : 'text/html', 'status_text' => isset(Response::$statusTexts[$statusCode]) ? Response::$statusTexts[$statusCode] : '', 'status_code' => $statusCode, 'request_query' => $request->query->all(), 'request_request' => $request->request->all(), 'request_headers' => $request->headers->all(), 'request_server' => $request->server->all(), 'request_cookies' => $request->cookies->all(), 'request_attributes' => $attributes, 'response_headers' => $responseHeaders, 'session_metadata' => $sessionMetadata, 'session_attributes' => $sessionAttributes, 'flashes' => $flashes, 'path_info' => $request->getPathInfo(), 'controller' => 'n/a', 'locale' => $request->getLocale(), ); if (isset($this->data['request_headers']['php-auth-pw'])) { $this->data['request_headers']['php-auth-pw'] = '******'; } if (isset($this->data['request_server']['PHP_AUTH_PW'])) { $this->data['request_server']['PHP_AUTH_PW'] = '******'; } if (isset($this->controllers[$request])) { $controller = $this->controllers[$request]; if (is_array($controller)) { try { $r = new \ReflectionMethod($controller[0], $controller[1]); $this->data['controller'] = array( 'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0], 'method' => $controller[1], 'file' => $r->getFilename(), 'line' => $r->getStartLine(), ); } catch (\ReflectionException $re) { if (is_callable($controller)) { // using __call or __callStatic $this->data['controller'] = array( 'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0], 'method' => $controller[1], 'file' => 'n/a', 'line' => 'n/a', ); } } } elseif ($controller instanceof \Closure) { $r = new \ReflectionFunction($controller); $this->data['controller'] = array( 'class' => $r->getName(), 'method' => null, 'file' => $r->getFilename(), 'line' => $r->getStartLine(), ); } else { $this->data['controller'] = (string) $controller ?: 'n/a'; } unset($this->controllers[$request]); } } public function getPathInfo() { return $this->data['path_info']; } public function getRequestRequest() { return new ParameterBag($this->data['request_request']); } public function getRequestQuery() { return new ParameterBag($this->data['request_query']); } public function getRequestHeaders() { return new HeaderBag($this->data['request_headers']); } public function getRequestServer() { return new ParameterBag($this->data['request_server']); } public function getRequestCookies() { return new ParameterBag($this->data['request_cookies']); } public function getRequestAttributes() { return new ParameterBag($this->data['request_attributes']); } public function getResponseHeaders() { return new ResponseHeaderBag($this->data['response_headers']); } public function getSessionMetadata() { return $this->data['session_metadata']; } public function getSessionAttributes() { return $this->data['session_attributes']; } public function getFlashes() { return $this->data['flashes']; } public function getContent() { return $this->data['content']; } public function getContentType() { return $this->data['content_type']; } public function getStatusText() { return $this->data['status_text']; } public function getStatusCode() { return $this->data['status_code']; } public function getFormat() { return $this->data['format']; } public function getLocale() { return $this->data['locale']; } /** * Gets the route name. * * The _route request attributes is automatically set by the Router Matcher. * * @return string The route */ public function getRoute() { return isset($this->data['request_attributes']['_route']) ? $this->data['request_attributes']['_route'] : ''; } /** * Gets the route parameters. * * The _route_params request attributes is automatically set by the RouterListener. * * @return array The parameters */ public function getRouteParams() { return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params'] : array(); } /** * Gets the controller. * * @return string The controller as a string */ public function getController() { return $this->data['controller']; } public function onKernelController(FilterControllerEvent $event) { $this->controllers[$event->getRequest()] = $event->getController(); } public static function getSubscribedEvents() { return array(KernelEvents::CONTROLLER => 'onKernelController'); } /** * {@inheritdoc} */ public function getName() { return 'request'; } private function getCookieHeader($name, $value, $expires, $path, $domain, $secure, $httponly) { $cookie = sprintf('%s=%s', $name, urlencode($value)); if (0 !== $expires) { if (is_numeric($expires)) { $expires = (int) $expires; } elseif ($expires instanceof \DateTime) { $expires = $expires->getTimestamp(); } else { $expires = strtotime($expires); if (false === $expires || -1 == $expires) { throw new \InvalidArgumentException(sprintf('The "expires" cookie parameter is not valid.', $expires)); } } $cookie .= '; expires='.str_replace('+0000', '', \DateTime::createFromFormat('U', $expires, new \DateTimeZone('GMT'))->format('D, d-M-Y H:i:s T')); } if ($domain) { $cookie .= '; domain='.$domain; } $cookie .= '; path='.$path; if ($secure) { $cookie .= '; secure'; } if ($httponly) { $cookie .= '; httponly'; } return $cookie; } } PK]^FF,HttpKernel/CacheWarmer/WarmableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Interface for classes that support warming their cache. * * @author Fabien Potencier */ interface WarmableInterface { /** * Warms up the cache. * * @param string $cacheDir The cache directory */ public function warmUp($cacheDir); } PK]8ee&HttpKernel/CacheWarmer/CacheWarmer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Abstract cache warmer that knows how to write a file to the cache. * * @author Fabien Potencier */ abstract class CacheWarmer implements CacheWarmerInterface { protected function writeCacheFile($file, $content) { $tmpFile = tempnam(dirname($file), basename($file)); if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) { @chmod($file, 0666 & ~umask()); return; } throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file)); } } PK]R!MM/HttpKernel/CacheWarmer/CacheWarmerAggregate.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Aggregates several cache warmers into a single one. * * @author Fabien Potencier */ class CacheWarmerAggregate implements CacheWarmerInterface { protected $warmers = array(); protected $optionalsEnabled = false; public function __construct(array $warmers = array()) { foreach ($warmers as $warmer) { $this->add($warmer); } } public function enableOptionalWarmers() { $this->optionalsEnabled = true; } /** * Warms up the cache. * * @param string $cacheDir The cache directory */ public function warmUp($cacheDir) { foreach ($this->warmers as $warmer) { if (!$this->optionalsEnabled && $warmer->isOptional()) { continue; } $warmer->warmUp($cacheDir); } } /** * Checks whether this warmer is optional or not. * * @return Boolean always true */ public function isOptional() { return false; } public function setWarmers(array $warmers) { $this->warmers = array(); foreach ($warmers as $warmer) { $this->add($warmer); } } public function add(CacheWarmerInterface $warmer) { $this->warmers[] = $warmer; } } PK]_S77/HttpKernel/CacheWarmer/CacheWarmerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Interface for classes able to warm up the cache. * * @author Fabien Potencier */ interface CacheWarmerInterface extends WarmableInterface { /** * Checks whether this warmer is optional or not. * * Optional warmers can be ignored on certain conditions. * * A warmer should return true if the cache can be * generated incrementally and on-demand. * * @return Boolean true if the warmer is optional, false otherwise */ public function isOptional(); } PK]\[HttpKernel/KernelInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\Config\Loader\LoaderInterface; /** * The Kernel is the heart of the Symfony system. * * It manages an environment made of bundles. * * @author Fabien Potencier * * @api */ interface KernelInterface extends HttpKernelInterface, \Serializable { /** * Returns an array of bundles to register. * * @return BundleInterface[] An array of bundle instances. * * @api */ public function registerBundles(); /** * Loads the container configuration. * * @param LoaderInterface $loader A LoaderInterface instance * * @api */ public function registerContainerConfiguration(LoaderInterface $loader); /** * Boots the current kernel. * * @api */ public function boot(); /** * Shutdowns the kernel. * * This method is mainly useful when doing functional testing. * * @api */ public function shutdown(); /** * Gets the registered bundle instances. * * @return BundleInterface[] An array of registered bundle instances * * @api */ public function getBundles(); /** * Checks if a given class name belongs to an active bundle. * * @param string $class A class name * * @return Boolean true if the class belongs to an active bundle, false otherwise * * @api */ public function isClassInActiveBundle($class); /** * Returns a bundle and optionally its descendants by its name. * * @param string $name Bundle name * @param Boolean $first Whether to return the first bundle only or together with its descendants * * @return BundleInterface|BundleInterface[] A BundleInterface instance or an array of BundleInterface instances if $first is false * * @throws \InvalidArgumentException when the bundle is not enabled * * @api */ public function getBundle($name, $first = true); /** * Returns the file path for a given resource. * * A Resource can be a file or a directory. * * The resource name must follow the following pattern: * * @BundleName/path/to/a/file.something * * where BundleName is the name of the bundle * and the remaining part is the relative path in the bundle. * * If $dir is passed, and the first segment of the path is Resources, * this method will look for a file named: * * $dir/BundleName/path/without/Resources * * @param string $name A resource name to locate * @param string $dir A directory where to look for the resource first * @param Boolean $first Whether to return the first path or paths for all matching bundles * * @return string|array The absolute path of the resource or an array if $first is false * * @throws \InvalidArgumentException if the file cannot be found or the name is not valid * @throws \RuntimeException if the name contains invalid/unsafe characters * * @api */ public function locateResource($name, $dir = null, $first = true); /** * Gets the name of the kernel. * * @return string The kernel name * * @api */ public function getName(); /** * Gets the environment. * * @return string The current environment * * @api */ public function getEnvironment(); /** * Checks if debug mode is enabled. * * @return Boolean true if debug mode is enabled, false otherwise * * @api */ public function isDebug(); /** * Gets the application root dir. * * @return string The application root dir * * @api */ public function getRootDir(); /** * Gets the current container. * * @return ContainerInterface A ContainerInterface instance * * @api */ public function getContainer(); /** * Gets the request start time (not available if debug is disabled). * * @return integer The request start timestamp * * @api */ public function getStartTime(); /** * Gets the cache directory. * * @return string The cache directory * * @api */ public function getCacheDir(); /** * Gets the log directory. * * @return string The log directory * * @api */ public function getLogDir(); /** * Gets the charset of the application. * * @return string The charset * * @api */ public function getCharset(); } PK]?.\\HttpKernel/Kernel.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\DependencyInjection\Loader\IniFileLoader; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass; use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\Config\Loader\DelegatingLoader; use Symfony\Component\Config\ConfigCache; use Symfony\Component\ClassLoader\ClassCollectionLoader; /** * The Kernel is the heart of the Symfony system. * * It manages an environment made of bundles. * * @author Fabien Potencier * * @api */ abstract class Kernel implements KernelInterface, TerminableInterface { /** * @var BundleInterface[] */ protected $bundles = array(); protected $bundleMap; protected $container; protected $rootDir; protected $environment; protected $debug; protected $booted = false; protected $name; protected $startTime; protected $loadClassCache; const VERSION = '2.4.3'; const VERSION_ID = '20403'; const MAJOR_VERSION = '2'; const MINOR_VERSION = '4'; const RELEASE_VERSION = '3'; const EXTRA_VERSION = ''; /** * Constructor. * * @param string $environment The environment * @param Boolean $debug Whether to enable debugging or not * * @api */ public function __construct($environment, $debug) { $this->environment = $environment; $this->debug = (Boolean) $debug; $this->rootDir = $this->getRootDir(); $this->name = $this->getName(); if ($this->debug) { $this->startTime = microtime(true); } $this->init(); } /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Move your logic in the constructor instead. */ public function init() { } public function __clone() { if ($this->debug) { $this->startTime = microtime(true); } $this->booted = false; $this->container = null; } /** * Boots the current kernel. * * @api */ public function boot() { if (true === $this->booted) { return; } if ($this->loadClassCache) { $this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]); } // init bundles $this->initializeBundles(); // init container $this->initializeContainer(); foreach ($this->getBundles() as $bundle) { $bundle->setContainer($this->container); $bundle->boot(); } $this->booted = true; } /** * {@inheritdoc} * * @api */ public function terminate(Request $request, Response $response) { if (false === $this->booted) { return; } if ($this->getHttpKernel() instanceof TerminableInterface) { $this->getHttpKernel()->terminate($request, $response); } } /** * {@inheritdoc} * * @api */ public function shutdown() { if (false === $this->booted) { return; } $this->booted = false; foreach ($this->getBundles() as $bundle) { $bundle->shutdown(); $bundle->setContainer(null); } $this->container = null; } /** * {@inheritdoc} * * @api */ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { if (false === $this->booted) { $this->boot(); } return $this->getHttpKernel()->handle($request, $type, $catch); } /** * Gets a HTTP kernel from the container * * @return HttpKernel */ protected function getHttpKernel() { return $this->container->get('http_kernel'); } /** * {@inheritdoc} * * @api */ public function getBundles() { return $this->bundles; } /** * {@inheritdoc} * * @api */ public function isClassInActiveBundle($class) { foreach ($this->getBundles() as $bundle) { if (0 === strpos($class, $bundle->getNamespace())) { return true; } } return false; } /** * {@inheritdoc} * * @api */ public function getBundle($name, $first = true) { if (!isset($this->bundleMap[$name])) { throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, get_class($this))); } if (true === $first) { return $this->bundleMap[$name][0]; } return $this->bundleMap[$name]; } /** * Returns the file path for a given resource. * * A Resource can be a file or a directory. * * The resource name must follow the following pattern: * * @/path/to/a/file.something * * where BundleName is the name of the bundle * and the remaining part is the relative path in the bundle. * * If $dir is passed, and the first segment of the path is "Resources", * this method will look for a file named: * * $dir//path/without/Resources * * before looking in the bundle resource folder. * * @param string $name A resource name to locate * @param string $dir A directory where to look for the resource first * @param Boolean $first Whether to return the first path or paths for all matching bundles * * @return string|array The absolute path of the resource or an array if $first is false * * @throws \InvalidArgumentException if the file cannot be found or the name is not valid * @throws \RuntimeException if the name contains invalid/unsafe * @throws \RuntimeException if a custom resource is hidden by a resource in a derived bundle * * @api */ public function locateResource($name, $dir = null, $first = true) { if ('@' !== $name[0]) { throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name)); } if (false !== strpos($name, '..')) { throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name)); } $bundleName = substr($name, 1); $path = ''; if (false !== strpos($bundleName, '/')) { list($bundleName, $path) = explode('/', $bundleName, 2); } $isResource = 0 === strpos($path, 'Resources') && null !== $dir; $overridePath = substr($path, 9); $resourceBundle = null; $bundles = $this->getBundle($bundleName, false); $files = array(); foreach ($bundles as $bundle) { if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) { if (null !== $resourceBundle) { throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.', $file, $resourceBundle, $dir.'/'.$bundles[0]->getName().$overridePath )); } if ($first) { return $file; } $files[] = $file; } if (file_exists($file = $bundle->getPath().'/'.$path)) { if ($first && !$isResource) { return $file; } $files[] = $file; $resourceBundle = $bundle->getName(); } } if (count($files) > 0) { return $first && $isResource ? $files[0] : $files; } throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name)); } /** * {@inheritdoc} * * @api */ public function getName() { if (null === $this->name) { $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir)); } return $this->name; } /** * {@inheritdoc} * * @api */ public function getEnvironment() { return $this->environment; } /** * {@inheritdoc} * * @api */ public function isDebug() { return $this->debug; } /** * {@inheritdoc} * * @api */ public function getRootDir() { if (null === $this->rootDir) { $r = new \ReflectionObject($this); $this->rootDir = str_replace('\\', '/', dirname($r->getFileName())); } return $this->rootDir; } /** * {@inheritdoc} * * @api */ public function getContainer() { return $this->container; } /** * Loads the PHP class cache. * * This methods only registers the fact that you want to load the cache classes. * The cache will actually only be loaded when the Kernel is booted. * * That optimization is mainly useful when using the HttpCache class in which * case the class cache is not loaded if the Response is in the cache. * * @param string $name The cache name prefix * @param string $extension File extension of the resulting file */ public function loadClassCache($name = 'classes', $extension = '.php') { $this->loadClassCache = array($name, $extension); } /** * Used internally. */ public function setClassCache(array $classes) { file_put_contents($this->getCacheDir().'/classes.map', sprintf('debug ? $this->startTime : -INF; } /** * {@inheritdoc} * * @api */ public function getCacheDir() { return $this->rootDir.'/cache/'.$this->environment; } /** * {@inheritdoc} * * @api */ public function getLogDir() { return $this->rootDir.'/logs'; } /** * {@inheritdoc} * * @api */ public function getCharset() { return 'UTF-8'; } protected function doLoadClassCache($name, $extension) { if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) { ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension); } } /** * Initializes the data structures related to the bundle management. * * - the bundles property maps a bundle name to the bundle instance, * - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first). * * @throws \LogicException if two bundles share a common name * @throws \LogicException if a bundle tries to extend a non-registered bundle * @throws \LogicException if a bundle tries to extend itself * @throws \LogicException if two bundles extend the same ancestor */ protected function initializeBundles() { // init bundles $this->bundles = array(); $topMostBundles = array(); $directChildren = array(); foreach ($this->registerBundles() as $bundle) { $name = $bundle->getName(); if (isset($this->bundles[$name])) { throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name)); } $this->bundles[$name] = $bundle; if ($parentName = $bundle->getParent()) { if (isset($directChildren[$parentName])) { throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName])); } if ($parentName == $name) { throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name)); } $directChildren[$parentName] = $name; } else { $topMostBundles[$name] = $bundle; } } // look for orphans if (!empty($directChildren) && count($diff = array_diff_key($directChildren, $this->bundles))) { $diff = array_keys($diff); throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0])); } // inheritance $this->bundleMap = array(); foreach ($topMostBundles as $name => $bundle) { $bundleMap = array($bundle); $hierarchy = array($name); while (isset($directChildren[$name])) { $name = $directChildren[$name]; array_unshift($bundleMap, $this->bundles[$name]); $hierarchy[] = $name; } foreach ($hierarchy as $bundle) { $this->bundleMap[$bundle] = $bundleMap; array_pop($bundleMap); } } } /** * Gets the container class. * * @return string The container class */ protected function getContainerClass() { return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer'; } /** * Gets the container's base class. * * All names except Container must be fully qualified. * * @return string */ protected function getContainerBaseClass() { return 'Container'; } /** * Initializes the service container. * * The cached version of the service container is used when fresh, otherwise the * container is built. */ protected function initializeContainer() { $class = $this->getContainerClass(); $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug); $fresh = true; if (!$cache->isFresh()) { $container = $this->buildContainer(); $container->compile(); $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); $fresh = false; } require_once $cache; $this->container = new $class(); $this->container->set('kernel', $this); if (!$fresh && $this->container->has('cache_warmer')) { $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')); } } /** * Returns the kernel parameters. * * @return array An array of kernel parameters */ protected function getKernelParameters() { $bundles = array(); foreach ($this->bundles as $name => $bundle) { $bundles[$name] = get_class($bundle); } return array_merge( array( 'kernel.root_dir' => $this->rootDir, 'kernel.environment' => $this->environment, 'kernel.debug' => $this->debug, 'kernel.name' => $this->name, 'kernel.cache_dir' => $this->getCacheDir(), 'kernel.logs_dir' => $this->getLogDir(), 'kernel.bundles' => $bundles, 'kernel.charset' => $this->getCharset(), 'kernel.container_class' => $this->getContainerClass(), ), $this->getEnvParameters() ); } /** * Gets the environment parameters. * * Only the parameters starting with "SYMFONY__" are considered. * * @return array An array of parameters */ protected function getEnvParameters() { $parameters = array(); foreach ($_SERVER as $key => $value) { if (0 === strpos($key, 'SYMFONY__')) { $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value; } } return $parameters; } /** * Builds the service container. * * @return ContainerBuilder The compiled service container * * @throws \RuntimeException */ protected function buildContainer() { foreach (array('cache' => $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) { if (!is_dir($dir)) { if (false === @mkdir($dir, 0777, true)) { throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir)); } } elseif (!is_writable($dir)) { throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir)); } } $container = $this->getContainerBuilder(); $container->addObjectResource($this); $this->prepareContainer($container); if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) { $container->merge($cont); } $container->addCompilerPass(new AddClassesToCachePass($this)); return $container; } /** * Prepares the ContainerBuilder before it is compiled. * * @param ContainerBuilder $container A ContainerBuilder instance */ protected function prepareContainer(ContainerBuilder $container) { $extensions = array(); foreach ($this->bundles as $bundle) { if ($extension = $bundle->getContainerExtension()) { $container->registerExtension($extension); $extensions[] = $extension->getAlias(); } if ($this->debug) { $container->addObjectResource($bundle); } } foreach ($this->bundles as $bundle) { $bundle->build($container); } // ensure these extensions are implicitly loaded $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions)); } /** * Gets a new ContainerBuilder instance used to build the service container. * * @return ContainerBuilder */ protected function getContainerBuilder() { $container = new ContainerBuilder(new ParameterBag($this->getKernelParameters())); if (class_exists('ProxyManager\Configuration')) { $container->setProxyInstantiator(new RuntimeInstantiator()); } return $container; } /** * Dumps the service container to PHP code in the cache. * * @param ConfigCache $cache The config cache * @param ContainerBuilder $container The service container * @param string $class The name of the class to generate * @param string $baseClass The name of the container's base class */ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass) { // cache the container $dumper = new PhpDumper($container); if (class_exists('ProxyManager\Configuration')) { $dumper->setProxyDumper(new ProxyDumper()); } $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass)); if (!$this->debug) { $content = static::stripComments($content); } $cache->write($content, $container->getResources()); } /** * Returns a loader for the container. * * @param ContainerInterface $container The service container * * @return DelegatingLoader The loader */ protected function getContainerLoader(ContainerInterface $container) { $locator = new FileLocator($this); $resolver = new LoaderResolver(array( new XmlFileLoader($container, $locator), new YamlFileLoader($container, $locator), new IniFileLoader($container, $locator), new PhpFileLoader($container, $locator), new ClosureLoader($container), )); return new DelegatingLoader($resolver); } /** * Removes comments from a PHP source string. * * We don't use the PHP php_strip_whitespace() function * as we want the content to be readable and well-formatted. * * @param string $source A PHP string * * @return string The PHP string with the comments removed */ public static function stripComments($source) { if (!function_exists('token_get_all')) { return $source; } $rawChunk = ''; $output = ''; $tokens = token_get_all($source); $ignoreSpace = false; for (reset($tokens); false !== $token = current($tokens); next($tokens)) { if (is_string($token)) { $rawChunk .= $token; } elseif (T_START_HEREDOC === $token[0]) { $output .= $rawChunk.$token[1]; do { $token = next($tokens); $output .= $token[1]; } while ($token[0] !== T_END_HEREDOC); $rawChunk = ''; } elseif (T_WHITESPACE === $token[0]) { if ($ignoreSpace) { $ignoreSpace = false; continue; } // replace multiple new lines with a single newline $rawChunk .= preg_replace(array('/\n{2,}/S'), "\n", $token[1]); } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) { $ignoreSpace = true; } else { $rawChunk .= $token[1]; // The PHP-open tag already has a new-line if (T_OPEN_TAG === $token[0]) { $ignoreSpace = true; } } } $output .= $rawChunk; return $output; } public function serialize() { return serialize(array($this->environment, $this->debug)); } public function unserialize($data) { list($environment, $debug) = unserialize($data); $this->__construct($environment, $debug); } } PK]d!HttpKernel/Config/FileLocator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Config; use Symfony\Component\Config\FileLocator as BaseFileLocator; use Symfony\Component\HttpKernel\KernelInterface; /** * FileLocator uses the KernelInterface to locate resources in bundles. * * @author Fabien Potencier */ class FileLocator extends BaseFileLocator { private $kernel; private $path; /** * Constructor. * * @param KernelInterface $kernel A KernelInterface instance * @param null|string $path The path the global resource directory * @param array $paths An array of paths where to look for resources */ public function __construct(KernelInterface $kernel, $path = null, array $paths = array()) { $this->kernel = $kernel; if (null !== $path) { $this->path = $path; $paths[] = $path; } parent::__construct($paths); } /** * {@inheritdoc} */ public function locate($file, $currentPath = null, $first = true) { if ('@' === $file[0]) { return $this->kernel->locateResource($file, $this->path, $first); } return parent::locate($file, $currentPath, $first); } } PK]JzHttpKernel/UriSigner.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; /** * Signs URIs. * * @author Fabien Potencier */ class UriSigner { private $secret; /** * Constructor. * * @param string $secret A secret */ public function __construct($secret) { $this->secret = $secret; } /** * Signs a URI. * * The given URI is signed by adding a _hash query string parameter * which value depends on the URI and the secret. * * @param string $uri A URI to sign * * @return string The signed URI */ public function sign($uri) { return $uri.(false === (strpos($uri, '?')) ? '?' : '&').'_hash='.$this->computeHash($uri); } /** * Checks that a URI contains the correct hash. * * The _hash query string parameter must be the last one * (as it is generated that way by the sign() method, it should * never be a problem). * * @param string $uri A signed URI * * @return Boolean True if the URI is signed correctly, false otherwise */ public function check($uri) { if (!preg_match('/^(.*)(?:\?|&)_hash=(.+?)$/', $uri, $matches)) { return false; } return $this->computeHash($matches[1]) === $matches[2]; } private function computeHash($uri) { return urlencode(base64_encode(hash_hmac('sha256', $uri, $this->secret, true))); } } PK]qK-##.HttpKernel/Fragment/InlineFragmentRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel. * * @author Fabien Potencier */ class InlineFragmentRenderer extends RoutableFragmentRenderer { private $kernel; private $dispatcher; /** * Constructor. * * @param HttpKernelInterface $kernel A HttpKernelInterface instance * @param EventDispatcherInterface $dispatcher A EventDispatcherInterface instance */ public function __construct(HttpKernelInterface $kernel, EventDispatcherInterface $dispatcher = null) { $this->kernel = $kernel; $this->dispatcher = $dispatcher; } /** * {@inheritdoc} * * Additional available options: * * * alt: an alternative URI to render in case of an error */ public function render($uri, Request $request, array $options = array()) { $reference = null; if ($uri instanceof ControllerReference) { $reference = $uri; // Remove attributes from the generated URI because if not, the Symfony // routing system will use them to populate the Request attributes. We don't // want that as we want to preserve objects (so we manually set Request attributes // below instead) $attributes = $reference->attributes; $reference->attributes = array(); // The request format and locale might have been overridden by the user foreach (array('_format', '_locale') as $key) { if (isset($attributes[$key])) { $reference->attributes[$key] = $attributes[$key]; } } $uri = $this->generateFragmentUri($uri, $request, false, false); $reference->attributes = array_merge($attributes, $reference->attributes); } $subRequest = $this->createSubRequest($uri, $request); // override Request attributes as they can be objects (which are not supported by the generated URI) if (null !== $reference) { $subRequest->attributes->add($reference->attributes); } $level = ob_get_level(); try { return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false); } catch (\Exception $e) { // we dispatch the exception event to trigger the logging // the response that comes back is simply ignored if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) { $event = new GetResponseForExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e); $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event); } // let's clean up the output buffers that were created by the sub-request while (ob_get_level() > $level) { ob_get_clean(); } if (isset($options['alt'])) { $alt = $options['alt']; unset($options['alt']); return $this->render($alt, $request, $options); } if (!isset($options['ignore_errors']) || !$options['ignore_errors']) { throw $e; } return new Response(); } } protected function createSubRequest($uri, Request $request) { $cookies = $request->cookies->all(); $server = $request->server->all(); // Override the arguments to emulate a sub-request. // Sub-request object will point to localhost as client ip and real client ip // will be included into trusted header for client ip try { if ($trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)) { $currentXForwardedFor = $request->headers->get($trustedHeaderName, ''); $server['HTTP_'.$trustedHeaderName] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp(); } } catch (\InvalidArgumentException $e) { // Do nothing } $server['REMOTE_ADDR'] = '127.0.0.1'; $subRequest = Request::create($uri, 'get', array(), $cookies, array(), $server); if ($request->headers->has('Surrogate-Capability')) { $subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability')); } if ($session = $request->getSession()) { $subRequest->setSession($session); } return $subRequest; } /** * {@inheritdoc} */ public function getName() { return 'inline'; } } PK]m3 3 0HttpKernel/Fragment/RoutableFragmentRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\EventListener\FragmentListener; /** * Adds the possibility to generate a fragment URI for a given Controller. * * @author Fabien Potencier */ abstract class RoutableFragmentRenderer implements FragmentRendererInterface { private $fragmentPath = '/_fragment'; /** * Sets the fragment path that triggers the fragment listener. * * @param string $path The path * * @see FragmentListener */ public function setFragmentPath($path) { $this->fragmentPath = $path; } /** * Generates a fragment URI for a given controller. * * @param ControllerReference $reference A ControllerReference instance * @param Request $request A Request instance * @param Boolean $absolute Whether to generate an absolute URL or not * @param Boolean $strict Whether to allow non-scalar attributes or not * * @return string A fragment URI */ protected function generateFragmentUri(ControllerReference $reference, Request $request, $absolute = false, $strict = true) { if ($strict) { $this->checkNonScalar($reference->attributes); } // We need to forward the current _format and _locale values as we don't have // a proper routing pattern to do the job for us. // This makes things inconsistent if you switch from rendering a controller // to rendering a route if the route pattern does not contain the special // _format and _locale placeholders. if (!isset($reference->attributes['_format'])) { $reference->attributes['_format'] = $request->getRequestFormat(); } if (!isset($reference->attributes['_locale'])) { $reference->attributes['_locale'] = $request->getLocale(); } $reference->attributes['_controller'] = $reference->controller; $reference->query['_path'] = http_build_query($reference->attributes, '', '&'); $path = $this->fragmentPath.'?'.http_build_query($reference->query, '', '&'); if ($absolute) { return $request->getUriForPath($path); } return $request->getBaseUrl().$path; } private function checkNonScalar($values) { foreach ($values as $key => $value) { if (is_array($value)) { $this->checkNonScalar($value); } elseif (!is_scalar($value) && null !== $value) { throw new \LogicException(sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key)); } } } } PK]jg +HttpKernel/Fragment/EsiFragmentRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\HttpCache\Esi; /** * Implements the ESI rendering strategy. * * @author Fabien Potencier */ class EsiFragmentRenderer extends RoutableFragmentRenderer { private $esi; private $inlineStrategy; /** * Constructor. * * The "fallback" strategy when ESI is not available should always be an * instance of InlineFragmentRenderer. * * @param Esi $esi An Esi instance * @param InlineFragmentRenderer $inlineStrategy The inline strategy to use when ESI is not supported */ public function __construct(Esi $esi = null, InlineFragmentRenderer $inlineStrategy) { $this->esi = $esi; $this->inlineStrategy = $inlineStrategy; } /** * {@inheritdoc} * * Note that if the current Request has no ESI capability, this method * falls back to use the inline rendering strategy. * * Additional available options: * * * alt: an alternative URI to render in case of an error * * comment: a comment to add when returning an esi:include tag * * @see Symfony\Component\HttpKernel\HttpCache\ESI */ public function render($uri, Request $request, array $options = array()) { if (!$this->esi || !$this->esi->hasSurrogateEsiCapability($request)) { return $this->inlineStrategy->render($uri, $request, $options); } if ($uri instanceof ControllerReference) { $uri = $this->generateFragmentUri($uri, $request); } $alt = isset($options['alt']) ? $options['alt'] : null; if ($alt instanceof ControllerReference) { $alt = $this->generateFragmentUri($alt, $request); } $tag = $this->esi->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : ''); return new Response($tag); } /** * {@inheritdoc} */ public function getName() { return 'esi'; } } PK]R'HttpKernel/Fragment/FragmentHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Controller\ControllerReference; /** * Renders a URI that represents a resource fragment. * * This class handles the rendering of resource fragments that are included into * a main resource. The handling of the rendering is managed by specialized renderers. * * This listener works in 2 modes: * * * 2.3 compatibility mode where you must call setRequest whenever the Request changes. * * 2.4+ mode where you must pass a RequestStack instance in the constructor. * * @author Fabien Potencier * * @see FragmentRendererInterface */ class FragmentHandler { private $debug; private $renderers = array(); private $request; private $requestStack; /** * Constructor. * * RequestStack will become required in 3.0. * * @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances * @param Boolean $debug Whether the debug mode is enabled or not * @param RequestStack|null $requestStack The Request stack that controls the lifecycle of requests */ public function __construct(array $renderers = array(), $debug = false, RequestStack $requestStack = null) { $this->requestStack = $requestStack; foreach ($renderers as $renderer) { $this->addRenderer($renderer); } $this->debug = $debug; } /** * Adds a renderer. * * @param FragmentRendererInterface $renderer A FragmentRendererInterface instance */ public function addRenderer(FragmentRendererInterface $renderer) { $this->renderers[$renderer->getName()] = $renderer; } /** * Sets the current Request. * * This method was used to synchronize the Request, but as the HttpKernel * is doing that automatically now, you should never call it directly. * It is kept public for BC with the 2.3 version. * * @param Request|null $request A Request instance * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function setRequest(Request $request = null) { $this->request = $request; } /** * Renders a URI and returns the Response content. * * Available options: * * * ignore_errors: true to return an empty string in case of an error * * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance * @param string $renderer The renderer name * @param array $options An array of options * * @return string|null The Response content or null when the Response is streamed * * @throws \InvalidArgumentException when the renderer does not exist * @throws \LogicException when the Request is not successful */ public function render($uri, $renderer = 'inline', array $options = array()) { if (!isset($options['ignore_errors'])) { $options['ignore_errors'] = !$this->debug; } if (!isset($this->renderers[$renderer])) { throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer)); } if (!$request = $this->getRequest()) { throw new \LogicException('Rendering a fragment can only be done when handling a Request.'); } return $this->deliver($this->renderers[$renderer]->render($uri, $request, $options)); } /** * Delivers the Response as a string. * * When the Response is a StreamedResponse, the content is streamed immediately * instead of being returned. * * @param Response $response A Response instance * * @return string|null The Response content or null when the Response is streamed * * @throws \RuntimeException when the Response is not successful */ protected function deliver(Response $response) { if (!$response->isSuccessful()) { throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->getRequest()->getUri(), $response->getStatusCode())); } if (!$response instanceof StreamedResponse) { return $response->getContent(); } $response->sendContent(); } private function getRequest() { return $this->requestStack ? $this->requestStack->getCurrentRequest() : $this->request; } } PK]5앾0HttpKernel/Fragment/HIncludeFragmentRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; if (!defined('ENT_SUBSTITUTE')) { define('ENT_SUBSTITUTE', 8); } use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Templating\EngineInterface; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\UriSigner; /** * Implements the Hinclude rendering strategy. * * @author Fabien Potencier */ class HIncludeFragmentRenderer extends RoutableFragmentRenderer { private $globalDefaultTemplate; private $signer; private $templating; private $charset; /** * Constructor. * * @param EngineInterface|\Twig_Environment $templating An EngineInterface or a \Twig_Environment instance * @param UriSigner $signer A UriSigner instance * @param string $globalDefaultTemplate The global default content (it can be a template name or the content) * @param string $charset */ public function __construct($templating = null, UriSigner $signer = null, $globalDefaultTemplate = null, $charset = 'utf-8') { $this->setTemplating($templating); $this->globalDefaultTemplate = $globalDefaultTemplate; $this->signer = $signer; $this->charset = $charset; } /** * Sets the templating engine to use to render the default content. * * @param EngineInterface|\Twig_Environment|null $templating An EngineInterface or a \Twig_Environment instance * * @throws \InvalidArgumentException */ public function setTemplating($templating) { if (null !== $templating && !$templating instanceof EngineInterface && !$templating instanceof \Twig_Environment) { throw new \InvalidArgumentException('The hinclude rendering strategy needs an instance of \Twig_Environment or Symfony\Component\Templating\EngineInterface'); } $this->templating = $templating; } /** * Checks if a templating engine has been set. * * @return Boolean true if the templating engine has been set, false otherwise */ public function hasTemplating() { return null !== $this->templating; } /** * {@inheritdoc} * * Additional available options: * * * default: The default content (it can be a template name or the content) * * id: An optional hx:include tag id attribute * * attributes: An optional array of hx:include tag attributes */ public function render($uri, Request $request, array $options = array()) { if ($uri instanceof ControllerReference) { if (null === $this->signer) { throw new \LogicException('You must use a proper URI when using the Hinclude rendering strategy or set a URL signer.'); } // we need to sign the absolute URI, but want to return the path only. $uri = substr($this->signer->sign($this->generateFragmentUri($uri, $request, true)), strlen($request->getSchemeAndHttpHost())); } // We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content. $uri = str_replace('&', '&', $uri); $template = isset($options['default']) ? $options['default'] : $this->globalDefaultTemplate; if (null !== $this->templating && $template && $this->templateExists($template)) { $content = $this->templating->render($template); } else { $content = $template; } $attributes = isset($options['attributes']) && is_array($options['attributes']) ? $options['attributes'] : array(); if (isset($options['id']) && $options['id']) { $attributes['id'] = $options['id']; } $renderedAttributes = ''; if (count($attributes) > 0) { foreach ($attributes as $attribute => $value) { $renderedAttributes .= sprintf( ' %s="%s"', htmlspecialchars($attribute, ENT_QUOTES | ENT_SUBSTITUTE, $this->charset, false), htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, $this->charset, false) ); } } return new Response(sprintf('%s', $uri, $renderedAttributes, $content)); } /** * @param string $template * * @return boolean */ private function templateExists($template) { if ($this->templating instanceof EngineInterface) { try { return $this->templating->exists($template); } catch (\InvalidArgumentException $e) { return false; } } $loader = $this->templating->getLoader(); if ($loader instanceof \Twig_ExistsLoaderInterface) { return $loader->exists($template); } try { $loader->getSource($template); return true; } catch (\Twig_Error_Loader $e) { } return false; } /** * {@inheritdoc} */ public function getName() { return 'hinclude'; } } PK]z1HttpKernel/Fragment/FragmentRendererInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpFoundation\Response; /** * Interface implemented by all rendering strategies. * * @author Fabien Potencier * * @see Symfony\Component\HttpKernel\FragmentRenderer */ interface FragmentRendererInterface { /** * Renders a URI and returns the Response content. * * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance * @param Request $request A Request instance * @param array $options An array of options * * @return Response A Response instance */ public function render($uri, Request $request, array $options = array()); /** * Gets the name of the strategy. * * @return string The strategy name */ public function getName(); } PK] KK!HttpKernel/Debug/ErrorHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Debug; use Symfony\Component\Debug\ErrorHandler as DebugErrorHandler; /** * ErrorHandler. * * @author Fabien Potencier * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead. */ class ErrorHandler extends DebugErrorHandler { } PK]eڮ55-HttpKernel/Debug/TraceableEventDispatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Debug; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Profiler\Profiler; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; /** * Collects some data about event listeners. * * This event dispatcher delegates the dispatching to another one. * * @author Fabien Potencier */ class TraceableEventDispatcher implements EventDispatcherInterface, TraceableEventDispatcherInterface { private $logger; private $called = array(); private $stopwatch; private $dispatcher; private $wrappedListeners = array(); private $firstCalledEvent = array(); private $lastEventId = 0; /** * Constructor. * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param Stopwatch $stopwatch A Stopwatch instance * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null) { $this->dispatcher = $dispatcher; $this->stopwatch = $stopwatch; $this->logger = $logger; } /** * Sets the profiler. * * The traceable event dispatcher does not use the profiler anymore. * The job is now done directly by the Profiler listener and the * data collectors themselves. * * @param Profiler|null $profiler A Profiler instance * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function setProfiler(Profiler $profiler = null) { } /** * {@inheritDoc} */ public function addListener($eventName, $listener, $priority = 0) { $this->dispatcher->addListener($eventName, $listener, $priority); } /** * {@inheritdoc} */ public function addSubscriber(EventSubscriberInterface $subscriber) { $this->dispatcher->addSubscriber($subscriber); } /** * {@inheritdoc} */ public function removeListener($eventName, $listener) { return $this->dispatcher->removeListener($eventName, $listener); } /** * {@inheritdoc} */ public function removeSubscriber(EventSubscriberInterface $subscriber) { return $this->dispatcher->removeSubscriber($subscriber); } /** * {@inheritdoc} */ public function getListeners($eventName = null) { return $this->dispatcher->getListeners($eventName); } /** * {@inheritdoc} */ public function hasListeners($eventName = null) { return $this->dispatcher->hasListeners($eventName); } /** * {@inheritdoc} */ public function dispatch($eventName, Event $event = null) { if (null === $event) { $event = new Event(); } $eventId = ++$this->lastEventId; $this->preDispatch($eventName, $eventId, $event); $e = $this->stopwatch->start($eventName, 'section'); $this->firstCalledEvent[$eventName] = $this->stopwatch->start($eventName.'.loading', 'event_listener_loading'); if (!$this->dispatcher->hasListeners($eventName)) { $this->firstCalledEvent[$eventName]->stop(); } $this->dispatcher->dispatch($eventName, $event); unset($this->firstCalledEvent[$eventName]); if ($e->isStarted()) { $e->stop(); } $this->postDispatch($eventName, $eventId, $event); return $event; } /** * {@inheritDoc} */ public function getCalledListeners() { return $this->called; } /** * {@inheritDoc} */ public function getNotCalledListeners() { $notCalled = array(); foreach ($this->getListeners() as $name => $listeners) { foreach ($listeners as $listener) { $info = $this->getListenerInfo($listener, null, $name); if (!isset($this->called[$name.'.'.$info['pretty']])) { $notCalled[$name.'.'.$info['pretty']] = $info; } } } return $notCalled; } /** * Proxies all method calls to the original event dispatcher. * * @param string $method The method name * @param array $arguments The method arguments * * @return mixed */ public function __call($method, $arguments) { return call_user_func_array(array($this->dispatcher, $method), $arguments); } /** * This is a private method and must not be used. * * This method is public because it is used in a closure. * Whenever Symfony will require PHP 5.4, this could be changed * to a proper private method. */ public function logSkippedListeners($eventName, $eventId, Event $event, $listener) { if (null === $this->logger) { return; } $info = $this->getListenerInfo($listener, $eventId, $eventName); $this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName)); $skippedListeners = $this->getListeners($eventName); $skipped = false; foreach ($skippedListeners as $skippedListener) { $skippedListener = $this->unwrapListener($skippedListener, $eventId); if ($skipped) { $info = $this->getListenerInfo($skippedListener, $eventId, $eventName); $this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName)); } if ($skippedListener === $listener) { $skipped = true; } } } /** * This is a private method. * * This method is public because it is used in a closure. * Whenever Symfony will require PHP 5.4, this could be changed * to a proper private method. */ public function preListenerCall($eventName, $eventId, $listener) { // is it the first called listener? if (isset($this->firstCalledEvent[$eventName])) { $this->firstCalledEvent[$eventName]->stop(); unset($this->firstCalledEvent[$eventName]); } $info = $this->getListenerInfo($listener, $eventId, $eventName); if (null !== $this->logger) { $this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty'])); } $this->called[$eventName.'.'.$info['pretty']] = $info; return $this->stopwatch->start(isset($info['class']) ? $info['class'] : $info['type'], 'event_listener'); } /** * Returns information about the listener * * @param object $listener The listener * @param string $eventName The event name * * @return array Information about the listener */ private function getListenerInfo($listener, $eventId, $eventName) { $listener = $this->unwrapListener($listener, $eventId); $info = array( 'event' => $eventName, ); if ($listener instanceof \Closure) { $info += array( 'type' => 'Closure', 'pretty' => 'closure' ); } elseif (is_string($listener)) { try { $r = new \ReflectionFunction($listener); $file = $r->getFileName(); $line = $r->getStartLine(); } catch (\ReflectionException $e) { $file = null; $line = null; } $info += array( 'type' => 'Function', 'function' => $listener, 'file' => $file, 'line' => $line, 'pretty' => $listener, ); } elseif (is_array($listener) || (is_object($listener) && is_callable($listener))) { if (!is_array($listener)) { $listener = array($listener, '__invoke'); } $class = is_object($listener[0]) ? get_class($listener[0]) : $listener[0]; try { $r = new \ReflectionMethod($class, $listener[1]); $file = $r->getFileName(); $line = $r->getStartLine(); } catch (\ReflectionException $e) { $file = null; $line = null; } $info += array( 'type' => 'Method', 'class' => $class, 'method' => $listener[1], 'file' => $file, 'line' => $line, 'pretty' => $class.'::'.$listener[1], ); } return $info; } private function preDispatch($eventName, $eventId, Event $event) { // wrap all listeners before they are called $this->wrappedListeners[$eventId] = new \SplObjectStorage(); $listeners = $this->dispatcher->getListeners($eventName); foreach ($listeners as $listener) { $this->dispatcher->removeListener($eventName, $listener); $wrapped = $this->wrapListener($eventName, $eventId, $listener); $this->wrappedListeners[$eventId][$wrapped] = $listener; $this->dispatcher->addListener($eventName, $wrapped); } switch ($eventName) { case KernelEvents::REQUEST: $this->stopwatch->openSection(); break; case KernelEvents::VIEW: case KernelEvents::RESPONSE: // stop only if a controller has been executed if ($this->stopwatch->isStarted('controller')) { $this->stopwatch->stop('controller'); } break; case KernelEvents::TERMINATE: $token = $event->getResponse()->headers->get('X-Debug-Token'); // There is a very special case when using builtin AppCache class as kernel wrapper, in the case // of an ESI request leading to a `stale` response [B] inside a `fresh` cached response [A]. // In this case, `$token` contains the [B] debug token, but the open `stopwatch` section ID // is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception // which must be caught. try { $this->stopwatch->openSection($token); } catch (\LogicException $e) {} break; } } private function postDispatch($eventName, $eventId, Event $event) { switch ($eventName) { case KernelEvents::CONTROLLER: $this->stopwatch->start('controller', 'section'); break; case KernelEvents::RESPONSE: $token = $event->getResponse()->headers->get('X-Debug-Token'); $this->stopwatch->stopSection($token); break; case KernelEvents::TERMINATE: // In the special case described in the `preDispatch` method above, the `$token` section // does not exist, then closing it throws an exception which must be caught. $token = $event->getResponse()->headers->get('X-Debug-Token'); try { $this->stopwatch->stopSection($token); } catch (\LogicException $e) {} break; } foreach ($this->wrappedListeners[$eventId] as $wrapped) { $this->dispatcher->removeListener($eventName, $wrapped); $this->dispatcher->addListener($eventName, $this->wrappedListeners[$eventId][$wrapped]); } unset($this->wrappedListeners[$eventId]); } private function wrapListener($eventName, $eventId, $listener) { $self = $this; return function (Event $event) use ($self, $eventName, $eventId, $listener) { $e = $self->preListenerCall($eventName, $eventId, $listener); call_user_func($listener, $event, $eventName, $self); if ($e->isStarted()) { $e->stop(); } if ($event->isPropagationStopped()) { $self->logSkippedListeners($eventName, $eventId, $event, $listener); } }; } private function unwrapListener($listener, $eventId) { // get the original listener if (is_object($listener)) { if (null === $eventId) { foreach (array_keys($this->wrappedListeners) as $eventId) { if (isset($this->wrappedListeners[$eventId][$listener])) { return $this->wrappedListeners[$eventId][$listener]; } } } elseif (isset($this->wrappedListeners[$eventId][$listener])) { return $this->wrappedListeners[$eventId][$listener]; } } return $listener; } } PK]9%HttpKernel/Debug/ExceptionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Debug; use Symfony\Component\Debug\ExceptionHandler as DebugExceptionHandler; /** * ExceptionHandler converts an exception to a Response object. * * @author Fabien Potencier * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead. */ class ExceptionHandler extends DebugExceptionHandler { } PK]N#FFHttpKernel/Client.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\BrowserKit\Client as BaseClient; use Symfony\Component\BrowserKit\Request as DomRequest; use Symfony\Component\BrowserKit\Response as DomResponse; use Symfony\Component\BrowserKit\Cookie as DomCookie; use Symfony\Component\BrowserKit\History; use Symfony\Component\BrowserKit\CookieJar; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Client simulates a browser and makes requests to a Kernel object. * * @author Fabien Potencier * * @api */ class Client extends BaseClient { protected $kernel; /** * Constructor. * * @param HttpKernelInterface $kernel An HttpKernel instance * @param array $server The server parameters (equivalent of $_SERVER) * @param History $history A History instance to store the browser history * @param CookieJar $cookieJar A CookieJar instance to store the cookies */ public function __construct(HttpKernelInterface $kernel, array $server = array(), History $history = null, CookieJar $cookieJar = null) { // These class properties must be set before calling the parent constructor, as it may depend on it. $this->kernel = $kernel; $this->followRedirects = false; parent::__construct($server, $history, $cookieJar); } /** * {@inheritdoc} * * @return Request|null A Request instance */ public function getRequest() { return parent::getRequest(); } /** * {@inheritdoc} * * @return Response|null A Response instance */ public function getResponse() { return parent::getResponse(); } /** * Makes a request. * * @param Request $request A Request instance * * @return Response A Response instance */ protected function doRequest($request) { $response = $this->kernel->handle($request); if ($this->kernel instanceof TerminableInterface) { $this->kernel->terminate($request, $response); } return $response; } /** * Returns the script to execute when the request must be insulated. * * @param Request $request A Request instance * * @return string */ protected function getScript($request) { $kernel = str_replace("'", "\\'", serialize($this->kernel)); $request = str_replace("'", "\\'", serialize($request)); $r = new \ReflectionClass('\\Symfony\\Component\\ClassLoader\\ClassLoader'); $requirePath = str_replace("'", "\\'", $r->getFileName()); $symfonyPath = str_replace("'", "\\'", realpath(__DIR__.'/../../..')); $code = <<addPrefix('Symfony', '$symfonyPath'); \$loader->register(); \$kernel = unserialize('$kernel'); \$request = unserialize('$request'); EOF; return $code.$this->getHandleScript(); } protected function getHandleScript() { return <<<'EOF' $response = $kernel->handle($request); if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) { $kernel->terminate($request, $response); } echo serialize($response); EOF; } /** * Converts the BrowserKit request to a HttpKernel request. * * @param DomRequest $request A DomRequest instance * * @return Request A Request instance */ protected function filterRequest(DomRequest $request) { $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent()); $httpRequest->files->replace($this->filterFiles($httpRequest->files->all())); return $httpRequest; } /** * Filters an array of files. * * This method created test instances of UploadedFile so that the move() * method can be called on those instances. * * If the size of a file is greater than the allowed size (from php.ini) then * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE. * * @see Symfony\Component\HttpFoundation\File\UploadedFile * * @param array $files An array of files * * @return array An array with all uploaded files marked as already moved */ protected function filterFiles(array $files) { $filtered = array(); foreach ($files as $key => $value) { if (is_array($value)) { $filtered[$key] = $this->filterFiles($value); } elseif ($value instanceof UploadedFile) { if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) { $filtered[$key] = new UploadedFile( '', $value->getClientOriginalName(), $value->getClientMimeType(), 0, UPLOAD_ERR_INI_SIZE, true ); } else { $filtered[$key] = new UploadedFile( $value->getPathname(), $value->getClientOriginalName(), $value->getClientMimeType(), $value->getClientSize(), $value->getError(), true ); } } else { $filtered[$key] = $value; } } return $filtered; } /** * Converts the HttpKernel response to a BrowserKit response. * * @param Response $response A Response instance * * @return DomResponse A DomResponse instance */ protected function filterResponse($response) { $headers = $response->headers->all(); if ($response->headers->getCookies()) { $cookies = array(); foreach ($response->headers->getCookies() as $cookie) { $cookies[] = new DomCookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); } $headers['Set-Cookie'] = $cookies; } // this is needed to support StreamedResponse ob_start(); $response->sendContent(); $content = ob_get_clean(); return new DomResponse($content, $response->getStatusCode(), $headers); } } PK]iY~2 2 /HttpKernel/Profiler/MemcacheProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Memcache Profiler Storage * * @author Andrej Hudec */ class MemcacheProfilerStorage extends BaseMemcacheProfilerStorage { /** * @var \Memcache */ private $memcache; /** * Internal convenience method that returns the instance of the Memcache * * @return \Memcache * * @throws \RuntimeException */ protected function getMemcache() { if (null === $this->memcache) { if (!preg_match('#^memcache://(?(?=\[.*\])\[(.*)\]|(.*)):(.*)$#', $this->dsn, $matches)) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Memcache with an invalid dsn "%s". The expected format is "memcache://[host]:port".', $this->dsn)); } $host = $matches[1] ?: $matches[2]; $port = $matches[3]; $memcache = new \Memcache(); $memcache->addServer($host, $port); $this->memcache = $memcache; } return $this->memcache; } /** * Set instance of the Memcache * * @param \Memcache $memcache */ public function setMemcache($memcache) { $this->memcache = $memcache; } /** * {@inheritdoc} */ protected function getValue($key) { return $this->getMemcache()->get($key); } /** * {@inheritdoc} */ protected function setValue($key, $value, $expiration = 0) { return $this->getMemcache()->set($key, $value, false, time() + $expiration); } /** * {@inheritdoc} */ protected function delete($key) { return $this->getMemcache()->delete($key); } /** * {@inheritdoc} */ protected function appendValue($key, $value, $expiration = 0) { $memcache = $this->getMemcache(); if (method_exists($memcache, 'append')) { // Memcache v3.0 if (!$result = $memcache->append($key, $value, false, $expiration)) { return $memcache->set($key, $value, false, $expiration); } return $result; } // simulate append in Memcache <3.0 $content = $memcache->get($key); return $memcache->set($key, $content.$value, false, $expiration); } } PK]\Y`+HttpKernel/Profiler/FileProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Storage for profiler using files. * * @author Alexandre Salomé */ class FileProfilerStorage implements ProfilerStorageInterface { /** * Folder where profiler data are stored. * * @var string */ private $folder; /** * Constructs the file storage using a "dsn-like" path. * * Example : "file:/path/to/the/storage/folder" * * @param string $dsn The DSN * * @throws \RuntimeException */ public function __construct($dsn) { if (0 !== strpos($dsn, 'file:')) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use FileStorage with an invalid dsn "%s". The expected format is "file:/path/to/the/storage/folder".', $dsn)); } $this->folder = substr($dsn, 5); if (!is_dir($this->folder)) { mkdir($this->folder, 0777, true); } } /** * {@inheritdoc} */ public function find($ip, $url, $limit, $method, $start = null, $end = null) { $file = $this->getIndexFilename(); if (!file_exists($file)) { return array(); } $file = fopen($file, 'r'); fseek($file, 0, SEEK_END); $result = array(); while (count($result) < $limit && $line = $this->readLineFromFile($file)) { list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent) = str_getcsv($line); $csvTime = (int) $csvTime; if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method)) { continue; } if (!empty($start) && $csvTime < $start) { continue; } if (!empty($end) && $csvTime > $end) { continue; } $result[$csvToken] = array( 'token' => $csvToken, 'ip' => $csvIp, 'method' => $csvMethod, 'url' => $csvUrl, 'time' => $csvTime, 'parent' => $csvParent, ); } fclose($file); return array_values($result); } /** * {@inheritdoc} */ public function purge() { $flags = \FilesystemIterator::SKIP_DOTS; $iterator = new \RecursiveDirectoryIterator($this->folder, $flags); $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST); foreach ($iterator as $file) { if (is_file($file)) { unlink($file); } else { rmdir($file); } } } /** * {@inheritdoc} */ public function read($token) { if (!$token || !file_exists($file = $this->getFilename($token))) { return null; } return $this->createProfileFromData($token, unserialize(file_get_contents($file))); } /** * {@inheritdoc} */ public function write(Profile $profile) { $file = $this->getFilename($profile->getToken()); $profileIndexed = is_file($file); if (!$profileIndexed) { // Create directory $dir = dirname($file); if (!is_dir($dir)) { mkdir($dir, 0777, true); } } // Store profile $data = array( 'token' => $profile->getToken(), 'parent' => $profile->getParentToken(), 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()), 'data' => $profile->getCollectors(), 'ip' => $profile->getIp(), 'method' => $profile->getMethod(), 'url' => $profile->getUrl(), 'time' => $profile->getTime(), ); if (false === file_put_contents($file, serialize($data))) { return false; } if (!$profileIndexed) { // Add to index if (false === $file = fopen($this->getIndexFilename(), 'a')) { return false; } fputcsv($file, array( $profile->getToken(), $profile->getIp(), $profile->getMethod(), $profile->getUrl(), $profile->getTime(), $profile->getParentToken(), )); fclose($file); } return true; } /** * Gets filename to store data, associated to the token. * * @param string $token * * @return string The profile filename */ protected function getFilename($token) { // Uses 4 last characters, because first are mostly the same. $folderA = substr($token, -2, 2); $folderB = substr($token, -4, 2); return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token; } /** * Gets the index filename. * * @return string The index filename */ protected function getIndexFilename() { return $this->folder.'/index.csv'; } /** * Reads a line in the file, backward. * * This function automatically skips the empty lines and do not include the line return in result value. * * @param resource $file The file resource, with the pointer placed at the end of the line to read * * @return mixed A string representing the line or null if beginning of file is reached */ protected function readLineFromFile($file) { $line = ''; $position = ftell($file); if (0 === $position) { return null; } while (true) { $chunkSize = min($position, 1024); $position -= $chunkSize; fseek($file, $position); if (0 === $chunkSize) { // bof reached break; } $buffer = fread($file, $chunkSize); if (false === ($upTo = strrpos($buffer, "\n"))) { $line = $buffer.$line; continue; } $position += $upTo; $line = substr($buffer, $upTo + 1).$line; fseek($file, max(0, $position), SEEK_SET); if ('' !== $line) { break; } } return '' === $line ? null : $line; } protected function createProfileFromData($token, $data, $parent = null) { $profile = new Profile($token); $profile->setIp($data['ip']); $profile->setMethod($data['method']); $profile->setUrl($data['url']); $profile->setTime($data['time']); $profile->setCollectors($data['data']); if (!$parent && $data['parent']) { $parent = $this->read($data['parent']); } if ($parent) { $profile->setParent($parent); } foreach ($data['children'] as $token) { if (!$token || !file_exists($file = $this->getFilename($token))) { continue; } $profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile)); } return $profile; } } PK]rLU0HttpKernel/Profiler/ProfilerStorageInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * ProfilerStorageInterface. * * @author Fabien Potencier */ interface ProfilerStorageInterface { /** * Finds profiler tokens for the given criteria. * * @param string $ip The IP * @param string $url The URL * @param string $limit The maximum number of tokens to return * @param string $method The request method * @param int|null $start The start date to search from * @param int|null $end The end date to search to * * @return array An array of tokens */ public function find($ip, $url, $limit, $method, $start = null, $end = null); /** * Reads data associated with the given token. * * The method returns false if the token does not exist in the storage. * * @param string $token A token * * @return Profile The profile associated with token */ public function read($token); /** * Saves a Profile. * * @param Profile $profile A Profile instance * * @return Boolean Write operation successful */ public function write(Profile $profile); /** * Purges all data from the database. */ public function purge(); } PK]t}[-HttpKernel/Profiler/SqliteProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * SqliteProfilerStorage stores profiling information in a SQLite database. * * @author Fabien Potencier */ class SqliteProfilerStorage extends PdoProfilerStorage { /** * @throws \RuntimeException When neither of SQLite3 or PDO_SQLite extension is enabled */ protected function initDb() { if (null === $this->db || $this->db instanceof \SQLite3) { if (0 !== strpos($this->dsn, 'sqlite')) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Sqlite with an invalid dsn "%s". The expected format is "sqlite:/path/to/the/db/file".', $this->dsn)); } if (class_exists('SQLite3')) { $db = new \SQLite3(substr($this->dsn, 7, strlen($this->dsn)), \SQLITE3_OPEN_READWRITE | \SQLITE3_OPEN_CREATE); if (method_exists($db, 'busyTimeout')) { // busyTimeout only exists for PHP >= 5.3.3 $db->busyTimeout(1000); } } elseif (class_exists('PDO') && in_array('sqlite', \PDO::getAvailableDrivers(), true)) { $db = new \PDO($this->dsn); } else { throw new \RuntimeException('You need to enable either the SQLite3 or PDO_SQLite extension for the profiler to run properly.'); } $db->exec('PRAGMA temp_store=MEMORY; PRAGMA journal_mode=MEMORY;'); $db->exec('CREATE TABLE IF NOT EXISTS sf_profiler_data (token STRING, data STRING, ip STRING, method STRING, url STRING, time INTEGER, parent STRING, created_at INTEGER)'); $db->exec('CREATE INDEX IF NOT EXISTS data_created_at ON sf_profiler_data (created_at)'); $db->exec('CREATE INDEX IF NOT EXISTS data_ip ON sf_profiler_data (ip)'); $db->exec('CREATE INDEX IF NOT EXISTS data_method ON sf_profiler_data (method)'); $db->exec('CREATE INDEX IF NOT EXISTS data_url ON sf_profiler_data (url)'); $db->exec('CREATE INDEX IF NOT EXISTS data_parent ON sf_profiler_data (parent)'); $db->exec('CREATE UNIQUE INDEX IF NOT EXISTS data_token ON sf_profiler_data (token)'); $this->db = $db; } return $this->db; } protected function exec($db, $query, array $args = array()) { if ($db instanceof \SQLite3) { $stmt = $this->prepareStatement($db, $query); foreach ($args as $arg => $val) { $stmt->bindValue($arg, $val, is_int($val) ? \SQLITE3_INTEGER : \SQLITE3_TEXT); } $res = $stmt->execute(); if (false === $res) { throw new \RuntimeException(sprintf('Error executing SQLite query "%s"', $query)); } $res->finalize(); } else { parent::exec($db, $query, $args); } } protected function fetch($db, $query, array $args = array()) { $return = array(); if ($db instanceof \SQLite3) { $stmt = $this->prepareStatement($db, $query, true); foreach ($args as $arg => $val) { $stmt->bindValue($arg, $val, is_int($val) ? \SQLITE3_INTEGER : \SQLITE3_TEXT); } $res = $stmt->execute(); while ($row = $res->fetchArray(\SQLITE3_ASSOC)) { $return[] = $row; } $res->finalize(); $stmt->close(); } else { $return = parent::fetch($db, $query, $args); } return $return; } /** * {@inheritdoc} */ protected function buildCriteria($ip, $url, $start, $end, $limit, $method) { $criteria = array(); $args = array(); if ($ip = preg_replace('/[^\d\.]/', '', $ip)) { $criteria[] = 'ip LIKE :ip'; $args[':ip'] = '%'.$ip.'%'; } if ($url) { $criteria[] = 'url LIKE :url ESCAPE "\"'; $args[':url'] = '%'.addcslashes($url, '%_\\').'%'; } if ($method) { $criteria[] = 'method = :method'; $args[':method'] = $method; } if (!empty($start)) { $criteria[] = 'time >= :start'; $args[':start'] = $start; } if (!empty($end)) { $criteria[] = 'time <= :end'; $args[':end'] = $end; } return array($criteria, $args); } protected function close($db) { if ($db instanceof \SQLite3) { $db->close(); } } } PK]TsX X ,HttpKernel/Profiler/MysqlProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * A ProfilerStorage for Mysql * * @author Jan Schumann */ class MysqlProfilerStorage extends PdoProfilerStorage { /** * {@inheritdoc} */ protected function initDb() { if (null === $this->db) { if (0 !== strpos($this->dsn, 'mysql')) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Mysql with an invalid dsn "%s". The expected format is "mysql:dbname=database_name;host=host_name".', $this->dsn)); } if (!class_exists('PDO') || !in_array('mysql', \PDO::getAvailableDrivers(), true)) { throw new \RuntimeException('You need to enable PDO_Mysql extension for the profiler to run properly.'); } $db = new \PDO($this->dsn, $this->username, $this->password); $db->exec('CREATE TABLE IF NOT EXISTS sf_profiler_data (token VARCHAR(255) PRIMARY KEY, data LONGTEXT, ip VARCHAR(64), method VARCHAR(6), url VARCHAR(255), time INTEGER UNSIGNED, parent VARCHAR(255), created_at INTEGER UNSIGNED, KEY (created_at), KEY (ip), KEY (method), KEY (url), KEY (parent))'); $this->db = $db; } return $this->db; } /** * {@inheritdoc} */ protected function buildCriteria($ip, $url, $start, $end, $limit, $method) { $criteria = array(); $args = array(); if ($ip = preg_replace('/[^\d\.]/', '', $ip)) { $criteria[] = 'ip LIKE :ip'; $args[':ip'] = '%'.$ip.'%'; } if ($url) { $criteria[] = 'url LIKE :url'; $args[':url'] = '%'.addcslashes($url, '%_\\').'%'; } if ($method) { $criteria[] = 'method = :method'; $args[':method'] = $method; } if (!empty($start)) { $criteria[] = 'time >= :start'; $args[':start'] = $start; } if (!empty($end)) { $criteria[] = 'time <= :end'; $args[':end'] = $end; } return array($criteria, $args); } } PK]N'',HttpKernel/Profiler/RedisProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * RedisProfilerStorage stores profiling information in Redis. * * @author Andrej Hudec * @author Stephane PY */ class RedisProfilerStorage implements ProfilerStorageInterface { const TOKEN_PREFIX = 'sf_profiler_'; const REDIS_OPT_SERIALIZER = 1; const REDIS_OPT_PREFIX = 2; const REDIS_SERIALIZER_NONE = 0; const REDIS_SERIALIZER_PHP = 1; protected $dsn; protected $lifetime; /** * @var \Redis */ private $redis; /** * Constructor. * * @param string $dsn A data source name * @param string $username Not used * @param string $password Not used * @param int $lifetime The lifetime to use for the purge */ public function __construct($dsn, $username = '', $password = '', $lifetime = 86400) { $this->dsn = $dsn; $this->lifetime = (int) $lifetime; } /** * {@inheritdoc} */ public function find($ip, $url, $limit, $method, $start = null, $end = null) { $indexName = $this->getIndexName(); if (!$indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE)) { return array(); } $profileList = array_reverse(explode("\n", $indexContent)); $result = array(); foreach ($profileList as $item) { if ($limit === 0) { break; } if ($item == '') { continue; } list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = explode("\t", $item, 6); $itemTime = (int) $itemTime; if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) { continue; } if (!empty($start) && $itemTime < $start) { continue; } if (!empty($end) && $itemTime > $end) { continue; } $result[] = array( 'token' => $itemToken, 'ip' => $itemIp, 'method' => $itemMethod, 'url' => $itemUrl, 'time' => $itemTime, 'parent' => $itemParent, ); --$limit; } return $result; } /** * {@inheritdoc} */ public function purge() { // delete only items from index $indexName = $this->getIndexName(); $indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE); if (!$indexContent) { return false; } $profileList = explode("\n", $indexContent); $result = array(); foreach ($profileList as $item) { if ($item == '') { continue; } if (false !== $pos = strpos($item, "\t")) { $result[] = $this->getItemName(substr($item, 0, $pos)); } } $result[] = $indexName; return $this->delete($result); } /** * {@inheritdoc} */ public function read($token) { if (empty($token)) { return false; } $profile = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP); if (false !== $profile) { $profile = $this->createProfileFromData($token, $profile); } return $profile; } /** * {@inheritdoc} */ public function write(Profile $profile) { $data = array( 'token' => $profile->getToken(), 'parent' => $profile->getParentToken(), 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()), 'data' => $profile->getCollectors(), 'ip' => $profile->getIp(), 'method' => $profile->getMethod(), 'url' => $profile->getUrl(), 'time' => $profile->getTime(), ); $profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken())); if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime, self::REDIS_SERIALIZER_PHP)) { if (!$profileIndexed) { // Add to index $indexName = $this->getIndexName(); $indexRow = implode("\t", array( $profile->getToken(), $profile->getIp(), $profile->getMethod(), $profile->getUrl(), $profile->getTime(), $profile->getParentToken(), ))."\n"; return $this->appendValue($indexName, $indexRow, $this->lifetime); } return true; } return false; } /** * Internal convenience method that returns the instance of Redis. * * @return \Redis * * @throws \RuntimeException */ protected function getRedis() { if (null === $this->redis) { $data = parse_url($this->dsn); if (false === $data || !isset($data['scheme']) || $data['scheme'] !== 'redis' || !isset($data['host']) || !isset($data['port'])) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Redis with an invalid dsn "%s". The minimal expected format is "redis://[host]:port".', $this->dsn)); } if (!extension_loaded('redis')) { throw new \RuntimeException('RedisProfilerStorage requires that the redis extension is loaded.'); } $redis = new \Redis(); $redis->connect($data['host'], $data['port']); if (isset($data['path'])) { $redis->select(substr($data['path'], 1)); } if (isset($data['pass'])) { $redis->auth($data['pass']); } $redis->setOption(self::REDIS_OPT_PREFIX, self::TOKEN_PREFIX); $this->redis = $redis; } return $this->redis; } /** * Set instance of the Redis * * @param \Redis $redis */ public function setRedis($redis) { $this->redis = $redis; } private function createProfileFromData($token, $data, $parent = null) { $profile = new Profile($token); $profile->setIp($data['ip']); $profile->setMethod($data['method']); $profile->setUrl($data['url']); $profile->setTime($data['time']); $profile->setCollectors($data['data']); if (!$parent && $data['parent']) { $parent = $this->read($data['parent']); } if ($parent) { $profile->setParent($parent); } foreach ($data['children'] as $token) { if (!$token) { continue; } if (!$childProfileData = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP)) { continue; } $profile->addChild($this->createProfileFromData($token, $childProfileData, $profile)); } return $profile; } /** * Gets the item name. * * @param string $token * * @return string */ private function getItemName($token) { $name = $token; if ($this->isItemNameValid($name)) { return $name; } return false; } /** * Gets the name of the index. * * @return string */ private function getIndexName() { $name = 'index'; if ($this->isItemNameValid($name)) { return $name; } return false; } private function isItemNameValid($name) { $length = strlen($name); if ($length > 2147483648) { throw new \RuntimeException(sprintf('The Redis item key "%s" is too long (%s bytes). Allowed maximum size is 2^31 bytes.', $name, $length)); } return true; } /** * Retrieves an item from the Redis server. * * @param string $key * @param int $serializer * * @return mixed */ private function getValue($key, $serializer = self::REDIS_SERIALIZER_NONE) { $redis = $this->getRedis(); $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer); return $redis->get($key); } /** * Stores an item on the Redis server under the specified key. * * @param string $key * @param mixed $value * @param int $expiration * @param int $serializer * * @return Boolean */ private function setValue($key, $value, $expiration = 0, $serializer = self::REDIS_SERIALIZER_NONE) { $redis = $this->getRedis(); $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer); return $redis->setex($key, $expiration, $value); } /** * Appends data to an existing item on the Redis server. * * @param string $key * @param string $value * @param int $expiration * * @return Boolean */ private function appendValue($key, $value, $expiration = 0) { $redis = $this->getRedis(); $redis->setOption(self::REDIS_OPT_SERIALIZER, self::REDIS_SERIALIZER_NONE); if ($redis->exists($key)) { $redis->append($key, $value); return $redis->setTimeout($key, $expiration); } return $redis->setex($key, $expiration, $value); } /** * Removes the specified keys. * * @param array $keys * * @return Boolean */ private function delete(array $keys) { return (bool) $this->getRedis()->delete($keys); } } PK]$ 0HttpKernel/Profiler/MemcachedProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Memcached Profiler Storage * * @author Andrej Hudec */ class MemcachedProfilerStorage extends BaseMemcacheProfilerStorage { /** * @var \Memcached */ private $memcached; /** * Internal convenience method that returns the instance of the Memcached * * @return \Memcached * * @throws \RuntimeException */ protected function getMemcached() { if (null === $this->memcached) { if (!preg_match('#^memcached://(?(?=\[.*\])\[(.*)\]|(.*)):(.*)$#', $this->dsn, $matches)) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Memcached with an invalid dsn "%s". The expected format is "memcached://[host]:port".', $this->dsn)); } $host = $matches[1] ?: $matches[2]; $port = $matches[3]; $memcached = new \Memcached(); // disable compression to allow appending $memcached->setOption(\Memcached::OPT_COMPRESSION, false); $memcached->addServer($host, $port); $this->memcached = $memcached; } return $this->memcached; } /** * Set instance of the Memcached * * @param \Memcached $memcached */ public function setMemcached($memcached) { $this->memcached = $memcached; } /** * {@inheritdoc} */ protected function getValue($key) { return $this->getMemcached()->get($key); } /** * {@inheritdoc} */ protected function setValue($key, $value, $expiration = 0) { return $this->getMemcached()->set($key, $value, time() + $expiration); } /** * {@inheritdoc} */ protected function delete($key) { return $this->getMemcached()->delete($key); } /** * {@inheritdoc} */ protected function appendValue($key, $value, $expiration = 0) { $memcached = $this->getMemcached(); if (!$result = $memcached->append($key, $value)) { return $memcached->set($key, $value, $expiration); } return $result; } } PK]   HttpKernel/Profiler/Profiler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Psr\Log\LoggerInterface; /** * Profiler. * * @author Fabien Potencier */ class Profiler { /** * @var ProfilerStorageInterface */ private $storage; /** * @var DataCollectorInterface[] */ private $collectors = array(); /** * @var LoggerInterface */ private $logger; /** * @var Boolean */ private $enabled = true; /** * Constructor. * * @param ProfilerStorageInterface $storage A ProfilerStorageInterface instance * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null) { $this->storage = $storage; $this->logger = $logger; } /** * Disables the profiler. */ public function disable() { $this->enabled = false; } /** * Enables the profiler. */ public function enable() { $this->enabled = true; } /** * Loads the Profile for the given Response. * * @param Response $response A Response instance * * @return Profile A Profile instance */ public function loadProfileFromResponse(Response $response) { if (!$token = $response->headers->get('X-Debug-Token')) { return false; } return $this->loadProfile($token); } /** * Loads the Profile for the given token. * * @param string $token A token * * @return Profile A Profile instance */ public function loadProfile($token) { return $this->storage->read($token); } /** * Saves a Profile. * * @param Profile $profile A Profile instance * * @return Boolean */ public function saveProfile(Profile $profile) { // late collect foreach ($profile->getCollectors() as $collector) { if ($collector instanceof LateDataCollectorInterface) { $collector->lateCollect(); } } if (!($ret = $this->storage->write($profile)) && null !== $this->logger) { $this->logger->warning('Unable to store the profiler information.'); } return $ret; } /** * Purges all data from the storage. */ public function purge() { $this->storage->purge(); } /** * Exports the current profiler data. * * @param Profile $profile A Profile instance * * @return string The exported data */ public function export(Profile $profile) { return base64_encode(serialize($profile)); } /** * Imports data into the profiler storage. * * @param string $data A data string as exported by the export() method * * @return Profile A Profile instance */ public function import($data) { $profile = unserialize(base64_decode($data)); if ($this->storage->read($profile->getToken())) { return false; } $this->saveProfile($profile); return $profile; } /** * Finds profiler tokens for the given criteria. * * @param string $ip The IP * @param string $url The URL * @param string $limit The maximum number of tokens to return * @param string $method The request method * @param string $start The start date to search from * @param string $end The end date to search to * * @return array An array of tokens * * @see http://fr2.php.net/manual/en/datetime.formats.php for the supported date/time formats */ public function find($ip, $url, $limit, $method, $start, $end) { if ('' != $start && null !== $start) { $start = new \DateTime($start); $start = $start->getTimestamp(); } else { $start = null; } if ('' != $end && null !== $end) { $end = new \DateTime($end); $end = $end->getTimestamp(); } else { $end = null; } return $this->storage->find($ip, $url, $limit, $method, $start, $end); } /** * Collects data for the given Response. * * @param Request $request A Request instance * @param Response $response A Response instance * @param \Exception $exception An exception instance if the request threw one * * @return Profile|null A Profile instance or null if the profiler is disabled */ public function collect(Request $request, Response $response, \Exception $exception = null) { if (false === $this->enabled) { return; } $profile = new Profile(substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6)); $profile->setTime(time()); $profile->setUrl($request->getUri()); $profile->setIp($request->getClientIp()); $profile->setMethod($request->getMethod()); $response->headers->set('X-Debug-Token', $profile->getToken()); foreach ($this->collectors as $collector) { $collector->collect($request, $response, $exception); // we need to clone for sub-requests $profile->addCollector(clone $collector); } return $profile; } /** * Gets the Collectors associated with this profiler. * * @return array An array of collectors */ public function all() { return $this->collectors; } /** * Sets the Collectors associated with this profiler. * * @param DataCollectorInterface[] $collectors An array of collectors */ public function set(array $collectors = array()) { $this->collectors = array(); foreach ($collectors as $collector) { $this->add($collector); } } /** * Adds a Collector. * * @param DataCollectorInterface $collector A DataCollectorInterface instance */ public function add(DataCollectorInterface $collector) { $this->collectors[$collector->getName()] = $collector; } /** * Returns true if a Collector for the given name exists. * * @param string $name A collector name * * @return Boolean */ public function has($name) { return isset($this->collectors[$name]); } /** * Gets a Collector by name. * * @param string $name A collector name * * @return DataCollectorInterface A DataCollectorInterface instance * * @throws \InvalidArgumentException if the collector does not exist */ public function get($name) { if (!isset($this->collectors[$name])) { throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); } return $this->collectors[$name]; } } PK]BWzll.HttpKernel/Profiler/MongoDbProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; class MongoDbProfilerStorage implements ProfilerStorageInterface { protected $dsn; protected $lifetime; private $mongo; /** * Constructor. * * @param string $dsn A data source name * @param string $username Not used * @param string $password Not used * @param integer $lifetime The lifetime to use for the purge */ public function __construct($dsn, $username = '', $password = '', $lifetime = 86400) { $this->dsn = $dsn; $this->lifetime = (int) $lifetime; } /** * {@inheritdoc} */ public function find($ip, $url, $limit, $method, $start = null, $end = null) { $cursor = $this->getMongo()->find($this->buildQuery($ip, $url, $method, $start, $end), array('_id', 'parent', 'ip', 'method', 'url', 'time'))->sort(array('time' => -1))->limit($limit); $tokens = array(); foreach ($cursor as $profile) { $tokens[] = $this->getData($profile); } return $tokens; } /** * {@inheritdoc} */ public function purge() { $this->getMongo()->remove(array()); } /** * {@inheritdoc} */ public function read($token) { $profile = $this->getMongo()->findOne(array('_id' => $token, 'data' => array('$exists' => true))); if (null !== $profile) { $profile = $this->createProfileFromData($this->getData($profile)); } return $profile; } /** * {@inheritdoc} */ public function write(Profile $profile) { $this->cleanup(); $record = array( '_id' => $profile->getToken(), 'parent' => $profile->getParentToken(), 'data' => base64_encode(serialize($profile->getCollectors())), 'ip' => $profile->getIp(), 'method' => $profile->getMethod(), 'url' => $profile->getUrl(), 'time' => $profile->getTime() ); $result = $this->getMongo()->update(array('_id' => $profile->getToken()), array_filter($record, function ($v) { return !empty($v); }), array('upsert' => true)); return (boolean) (isset($result['ok']) ? $result['ok'] : $result); } /** * Internal convenience method that returns the instance of the MongoDB Collection * * @return \MongoCollection * * @throws \RuntimeException */ protected function getMongo() { if (null !== $this->mongo) { return $this->mongo; } if (!$parsedDsn = $this->parseDsn($this->dsn)) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use MongoDB with an invalid dsn "%s". The expected format is "mongodb://[user:pass@]host/database/collection"', $this->dsn)); } list($server, $database, $collection) = $parsedDsn; $mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? '\Mongo' : '\MongoClient'; $mongo = new $mongoClass($server); return $this->mongo = $mongo->selectCollection($database, $collection); } /** * @param array $data * * @return Profile */ protected function createProfileFromData(array $data) { $profile = $this->getProfile($data); if ($data['parent']) { $parent = $this->getMongo()->findOne(array('_id' => $data['parent'], 'data' => array('$exists' => true))); if ($parent) { $profile->setParent($this->getProfile($this->getData($parent))); } } $profile->setChildren($this->readChildren($data['token'])); return $profile; } /** * @param string $token * * @return Profile[] An array of Profile instances */ protected function readChildren($token) { $profiles = array(); $cursor = $this->getMongo()->find(array('parent' => $token, 'data' => array('$exists' => true))); foreach ($cursor as $d) { $profiles[] = $this->getProfile($this->getData($d)); } return $profiles; } protected function cleanup() { $this->getMongo()->remove(array('time' => array('$lt' => time() - $this->lifetime))); } /** * @param string $ip * @param string $url * @param string $method * @param int $start * @param int $end * * @return array */ private function buildQuery($ip, $url, $method, $start, $end) { $query = array(); if (!empty($ip)) { $query['ip'] = $ip; } if (!empty($url)) { $query['url'] = $url; } if (!empty($method)) { $query['method'] = $method; } if (!empty($start) || !empty($end)) { $query['time'] = array(); } if (!empty($start)) { $query['time']['$gte'] = $start; } if (!empty($end)) { $query['time']['$lte'] = $end; } return $query; } /** * @param array $data * * @return array */ private function getData(array $data) { return array( 'token' => $data['_id'], 'parent' => isset($data['parent']) ? $data['parent'] : null, 'ip' => isset($data['ip']) ? $data['ip'] : null, 'method' => isset($data['method']) ? $data['method'] : null, 'url' => isset($data['url']) ? $data['url'] : null, 'time' => isset($data['time']) ? $data['time'] : null, 'data' => isset($data['data']) ? $data['data'] : null, ); } /** * @param array $data * * @return Profile */ private function getProfile(array $data) { $profile = new Profile($data['token']); $profile->setIp($data['ip']); $profile->setMethod($data['method']); $profile->setUrl($data['url']); $profile->setTime($data['time']); $profile->setCollectors(unserialize(base64_decode($data['data']))); return $profile; } /** * @param string $dsn * * @return null|array Array($server, $database, $collection) */ private function parseDsn($dsn) { if (!preg_match('#^(mongodb://.*)/(.*)/(.*)$#', $dsn, $matches)) { return; } $server = $matches[1]; $database = $matches[2]; $collection = $matches[3]; preg_match('#^mongodb://(([^:]+):?(.*)(?=@))?@?([^/]*)(.*)$#', $server, $matchesServer); if ('' == $matchesServer[5] && '' != $matches[2]) { $server .= '/'.$matches[2]; } return array($server, $database, $collection); } } PK] HttpKernel/Profiler/Profile.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; /** * Profile. * * @author Fabien Potencier */ class Profile { private $token; /** * @var DataCollectorInterface[] */ private $collectors = array(); private $ip; private $method; private $url; private $time; /** * @var Profile */ private $parent; /** * @var Profile[] */ private $children = array(); /** * Constructor. * * @param string $token The token */ public function __construct($token) { $this->token = $token; } /** * Sets the token. * * @param string $token The token */ public function setToken($token) { $this->token = $token; } /** * Gets the token. * * @return string The token */ public function getToken() { return $this->token; } /** * Sets the parent token * * @param Profile $parent The parent Profile */ public function setParent(Profile $parent) { $this->parent = $parent; } /** * Returns the parent profile. * * @return Profile The parent profile */ public function getParent() { return $this->parent; } /** * Returns the parent token. * * @return null|string The parent token */ public function getParentToken() { return $this->parent ? $this->parent->getToken() : null; } /** * Returns the IP. * * @return string The IP */ public function getIp() { return $this->ip; } /** * Sets the IP. * * @param string $ip */ public function setIp($ip) { $this->ip = $ip; } /** * Returns the request method. * * @return string The request method */ public function getMethod() { return $this->method; } public function setMethod($method) { $this->method = $method; } /** * Returns the URL. * * @return string The URL */ public function getUrl() { return $this->url; } public function setUrl($url) { $this->url = $url; } /** * Returns the time. * * @return string The time */ public function getTime() { if (null === $this->time) { return 0; } return $this->time; } public function setTime($time) { $this->time = $time; } /** * Finds children profilers. * * @return Profile[] An array of Profile */ public function getChildren() { return $this->children; } /** * Sets children profiler. * * @param Profile[] $children An array of Profile */ public function setChildren(array $children) { $this->children = array(); foreach ($children as $child) { $this->addChild($child); } } /** * Adds the child token * * @param Profile $child The child Profile */ public function addChild(Profile $child) { $this->children[] = $child; $child->setParent($this); } /** * Gets a Collector by name. * * @param string $name A collector name * * @return DataCollectorInterface A DataCollectorInterface instance * * @throws \InvalidArgumentException if the collector does not exist */ public function getCollector($name) { if (!isset($this->collectors[$name])) { throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); } return $this->collectors[$name]; } /** * Gets the Collectors associated with this profile. * * @return DataCollectorInterface[] */ public function getCollectors() { return $this->collectors; } /** * Sets the Collectors associated with this profile. * * @param DataCollectorInterface[] $collectors */ public function setCollectors(array $collectors) { $this->collectors = array(); foreach ($collectors as $collector) { $this->addCollector($collector); } } /** * Adds a Collector. * * @param DataCollectorInterface $collector A DataCollectorInterface instance */ public function addCollector(DataCollectorInterface $collector) { $this->collectors[$collector->getName()] = $collector; } /** * Returns true if a Collector for the given name exists. * * @param string $name A collector name * * @return Boolean */ public function hasCollector($name) { return isset($this->collectors[$name]); } public function __sleep() { return array('token', 'parent', 'children', 'collectors', 'ip', 'method', 'url', 'time'); } } PK]*HttpKernel/Profiler/PdoProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Base PDO storage for profiling information in a PDO database. * * @author Fabien Potencier * @author Jan Schumann */ abstract class PdoProfilerStorage implements ProfilerStorageInterface { protected $dsn; protected $username; protected $password; protected $lifetime; protected $db; /** * Constructor. * * @param string $dsn A data source name * @param string $username The username for the database * @param string $password The password for the database * @param integer $lifetime The lifetime to use for the purge */ public function __construct($dsn, $username = '', $password = '', $lifetime = 86400) { $this->dsn = $dsn; $this->username = $username; $this->password = $password; $this->lifetime = (int) $lifetime; } /** * {@inheritdoc} */ public function find($ip, $url, $limit, $method, $start = null, $end = null) { if (null === $start) { $start = 0; } if (null === $end) { $end = time(); } list($criteria, $args) = $this->buildCriteria($ip, $url, $start, $end, $limit, $method); $criteria = $criteria ? 'WHERE '.implode(' AND ', $criteria) : ''; $db = $this->initDb(); $tokens = $this->fetch($db, 'SELECT token, ip, method, url, time, parent FROM sf_profiler_data '.$criteria.' ORDER BY time DESC LIMIT '.((integer) $limit), $args); $this->close($db); return $tokens; } /** * {@inheritdoc} */ public function read($token) { $db = $this->initDb(); $args = array(':token' => $token); $data = $this->fetch($db, 'SELECT data, parent, ip, method, url, time FROM sf_profiler_data WHERE token = :token LIMIT 1', $args); $this->close($db); if (isset($data[0]['data'])) { return $this->createProfileFromData($token, $data[0]); } return null; } /** * {@inheritdoc} */ public function write(Profile $profile) { $db = $this->initDb(); $args = array( ':token' => $profile->getToken(), ':parent' => $profile->getParentToken(), ':data' => base64_encode(serialize($profile->getCollectors())), ':ip' => $profile->getIp(), ':method' => $profile->getMethod(), ':url' => $profile->getUrl(), ':time' => $profile->getTime(), ':created_at' => time(), ); try { if ($this->has($profile->getToken())) { $this->exec($db, 'UPDATE sf_profiler_data SET parent = :parent, data = :data, ip = :ip, method = :method, url = :url, time = :time, created_at = :created_at WHERE token = :token', $args); } else { $this->exec($db, 'INSERT INTO sf_profiler_data (token, parent, data, ip, method, url, time, created_at) VALUES (:token, :parent, :data, :ip, :method, :url, :time, :created_at)', $args); } $this->cleanup(); $status = true; } catch (\Exception $e) { $status = false; } $this->close($db); return $status; } /** * {@inheritdoc} */ public function purge() { $db = $this->initDb(); $this->exec($db, 'DELETE FROM sf_profiler_data'); $this->close($db); } /** * Build SQL criteria to fetch records by ip and url * * @param string $ip The IP * @param string $url The URL * @param string $start The start period to search from * @param string $end The end period to search to * @param string $limit The maximum number of tokens to return * @param string $method The request method * * @return array An array with (criteria, args) */ abstract protected function buildCriteria($ip, $url, $start, $end, $limit, $method); /** * Initializes the database * * @throws \RuntimeException When the requested database driver is not installed */ abstract protected function initDb(); protected function cleanup() { $db = $this->initDb(); $this->exec($db, 'DELETE FROM sf_profiler_data WHERE created_at < :time', array(':time' => time() - $this->lifetime)); $this->close($db); } protected function exec($db, $query, array $args = array()) { $stmt = $this->prepareStatement($db, $query); foreach ($args as $arg => $val) { $stmt->bindValue($arg, $val, is_int($val) ? \PDO::PARAM_INT : \PDO::PARAM_STR); } $success = $stmt->execute(); if (!$success) { throw new \RuntimeException(sprintf('Error executing query "%s"', $query)); } } protected function prepareStatement($db, $query) { try { $stmt = $db->prepare($query); } catch (\Exception $e) { $stmt = false; } if (false === $stmt) { throw new \RuntimeException('The database cannot successfully prepare the statement'); } return $stmt; } protected function fetch($db, $query, array $args = array()) { $stmt = $this->prepareStatement($db, $query); foreach ($args as $arg => $val) { $stmt->bindValue($arg, $val, is_int($val) ? \PDO::PARAM_INT : \PDO::PARAM_STR); } $stmt->execute(); $return = $stmt->fetchAll(\PDO::FETCH_ASSOC); return $return; } protected function close($db) { } protected function createProfileFromData($token, $data, $parent = null) { $profile = new Profile($token); $profile->setIp($data['ip']); $profile->setMethod($data['method']); $profile->setUrl($data['url']); $profile->setTime($data['time']); $profile->setCollectors(unserialize(base64_decode($data['data']))); if (!$parent && !empty($data['parent'])) { $parent = $this->read($data['parent']); } if ($parent) { $profile->setParent($parent); } $profile->setChildren($this->readChildren($token, $profile)); return $profile; } /** * Reads the child profiles for the given token. * * @param string $token The parent token * @param string $parent The parent instance * * @return Profile[] An array of Profile instance */ protected function readChildren($token, $parent) { $db = $this->initDb(); $data = $this->fetch($db, 'SELECT token, data, ip, method, url, time FROM sf_profiler_data WHERE parent = :token', array(':token' => $token)); $this->close($db); if (!$data) { return array(); } $profiles = array(); foreach ($data as $d) { $profiles[] = $this->createProfileFromData($d['token'], $d, $parent); } return $profiles; } /** * Returns whether data for the given token already exists in storage. * * @param string $token The profile token * * @return string */ protected function has($token) { $db = $this->initDb(); $tokenExists = $this->fetch($db, 'SELECT 1 FROM sf_profiler_data WHERE token = :token LIMIT 1', array(':token' => $token)); $this->close($db); return !empty($tokenExists); } } PK]t3HttpKernel/Profiler/BaseMemcacheProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Base Memcache storage for profiling information in a Memcache. * * @author Andrej Hudec */ abstract class BaseMemcacheProfilerStorage implements ProfilerStorageInterface { const TOKEN_PREFIX = 'sf_profiler_'; protected $dsn; protected $lifetime; /** * Constructor. * * @param string $dsn A data source name * @param string $username * @param string $password * @param int $lifetime The lifetime to use for the purge */ public function __construct($dsn, $username = '', $password = '', $lifetime = 86400) { $this->dsn = $dsn; $this->lifetime = (int) $lifetime; } /** * {@inheritdoc} */ public function find($ip, $url, $limit, $method, $start = null, $end = null) { $indexName = $this->getIndexName(); $indexContent = $this->getValue($indexName); if (!$indexContent) { return array(); } $profileList = explode("\n", $indexContent); $result = array(); foreach ($profileList as $item) { if ($limit === 0) { break; } if ($item=='') { continue; } list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = explode("\t", $item, 6); $itemTime = (int) $itemTime; if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) { continue; } if (!empty($start) && $itemTime < $start) { continue; } if (!empty($end) && $itemTime > $end) { continue; } $result[$itemToken] = array( 'token' => $itemToken, 'ip' => $itemIp, 'method' => $itemMethod, 'url' => $itemUrl, 'time' => $itemTime, 'parent' => $itemParent, ); --$limit; } usort($result, function ($a, $b) { if ($a['time'] === $b['time']) { return 0; } return $a['time'] > $b['time'] ? -1 : 1; }); return $result; } /** * {@inheritdoc} */ public function purge() { // delete only items from index $indexName = $this->getIndexName(); $indexContent = $this->getValue($indexName); if (!$indexContent) { return false; } $profileList = explode("\n", $indexContent); foreach ($profileList as $item) { if ($item == '') { continue; } if (false !== $pos = strpos($item, "\t")) { $this->delete($this->getItemName(substr($item, 0, $pos))); } } return $this->delete($indexName); } /** * {@inheritdoc} */ public function read($token) { if (empty($token)) { return false; } $profile = $this->getValue($this->getItemName($token)); if (false !== $profile) { $profile = $this->createProfileFromData($token, $profile); } return $profile; } /** * {@inheritdoc} */ public function write(Profile $profile) { $data = array( 'token' => $profile->getToken(), 'parent' => $profile->getParentToken(), 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()), 'data' => $profile->getCollectors(), 'ip' => $profile->getIp(), 'method' => $profile->getMethod(), 'url' => $profile->getUrl(), 'time' => $profile->getTime(), ); $profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken())); if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime)) { if (!$profileIndexed) { // Add to index $indexName = $this->getIndexName(); $indexRow = implode("\t", array( $profile->getToken(), $profile->getIp(), $profile->getMethod(), $profile->getUrl(), $profile->getTime(), $profile->getParentToken(), ))."\n"; return $this->appendValue($indexName, $indexRow, $this->lifetime); } return true; } return false; } /** * Retrieve item from the memcache server * * @param string $key * * @return mixed */ abstract protected function getValue($key); /** * Store an item on the memcache server under the specified key * * @param string $key * @param mixed $value * @param int $expiration * * @return boolean */ abstract protected function setValue($key, $value, $expiration = 0); /** * Delete item from the memcache server * * @param string $key * * @return boolean */ abstract protected function delete($key); /** * Append data to an existing item on the memcache server * @param string $key * @param string $value * @param int $expiration * * @return boolean */ abstract protected function appendValue($key, $value, $expiration = 0); private function createProfileFromData($token, $data, $parent = null) { $profile = new Profile($token); $profile->setIp($data['ip']); $profile->setMethod($data['method']); $profile->setUrl($data['url']); $profile->setTime($data['time']); $profile->setCollectors($data['data']); if (!$parent && $data['parent']) { $parent = $this->read($data['parent']); } if ($parent) { $profile->setParent($parent); } foreach ($data['children'] as $token) { if (!$token) { continue; } if (!$childProfileData = $this->getValue($this->getItemName($token))) { continue; } $profile->addChild($this->createProfileFromData($token, $childProfileData, $profile)); } return $profile; } /** * Get item name * * @param string $token * * @return string */ private function getItemName($token) { $name = self::TOKEN_PREFIX.$token; if ($this->isItemNameValid($name)) { return $name; } return false; } /** * Get name of index * * @return string */ private function getIndexName() { $name = self::TOKEN_PREFIX.'index'; if ($this->isItemNameValid($name)) { return $name; } return false; } private function isItemNameValid($name) { $length = strlen($name); if ($length > 250) { throw new \RuntimeException(sprintf('The memcache item key "%s" is too long (%s bytes). Allowed maximum size is 250 bytes.', $name, $length)); } return true; } } PK]٨.kk8HttpKernel/Event/GetResponseForControllerResultEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; /** * Allows to create a response for the return value of a controller * * Call setResponse() to set the response that will be returned for the * current request. The propagation of this event is stopped as soon as a * response is set. * * @author Bernhard Schussek * * @api */ class GetResponseForControllerResultEvent extends GetResponseEvent { /** * The return value of the controller * * @var mixed */ private $controllerResult; public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, $controllerResult) { parent::__construct($kernel, $request, $requestType); $this->controllerResult = $controllerResult; } /** * Returns the return value of the controller. * * @return mixed The controller return value * * @api */ public function getControllerResult() { return $this->controllerResult; } /** * Assigns the return value of the controller. * * @param mixed $controllerResult The controller return value * * @api */ public function setControllerResult($controllerResult) { $this->controllerResult = $controllerResult; } } PK]91HttpKernel/Event/GetResponseForExceptionEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; /** * Allows to create a response for a thrown exception * * Call setResponse() to set the response that will be returned for the * current request. The propagation of this event is stopped as soon as a * response is set. * * You can also call setException() to replace the thrown exception. This * exception will be thrown if no response is set during processing of this * event. * * @author Bernhard Schussek * * @api */ class GetResponseForExceptionEvent extends GetResponseEvent { /** * The exception object * @var \Exception */ private $exception; public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, \Exception $e) { parent::__construct($kernel, $request, $requestType); $this->setException($e); } /** * Returns the thrown exception * * @return \Exception The thrown exception * * @api */ public function getException() { return $this->exception; } /** * Replaces the thrown exception * * This exception will be thrown if no response is set in the event. * * @param \Exception $exception The thrown exception * * @api */ public function setException(\Exception $exception) { $this->exception = $exception; } } PK]% *HttpKernel/Event/FilterControllerEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; /** * Allows filtering of a controller callable * * You can call getController() to retrieve the current controller. With * setController() you can set a new controller that is used in the processing * of the request. * * Controllers should be callables. * * @author Bernhard Schussek * * @api */ class FilterControllerEvent extends KernelEvent { /** * The current controller * @var callable */ private $controller; public function __construct(HttpKernelInterface $kernel, $controller, Request $request, $requestType) { parent::__construct($kernel, $request, $requestType); $this->setController($controller); } /** * Returns the current controller * * @return callable * * @api */ public function getController() { return $this->controller; } /** * Sets a new controller * * @param callable $controller * * @throws \LogicException * * @api */ public function setController($controller) { // controller must be a callable if (!is_callable($controller)) { throw new \LogicException(sprintf('The controller must be a callable (%s given).', $this->varToString($controller))); } $this->controller = $controller; } private function varToString($var) { if (is_object($var)) { return sprintf('Object(%s)', get_class($var)); } if (is_array($var)) { $a = array(); foreach ($var as $k => $v) { $a[] = sprintf('%s => %s', $k, $this->varToString($v)); } return sprintf("Array(%s)", implode(', ', $a)); } if (is_resource($var)) { return sprintf('Resource(%s)', get_resource_type($var)); } if (null === $var) { return 'null'; } if (false === $var) { return 'false'; } if (true === $var) { return 'true'; } return (string) $var; } } PK],&&&HttpKernel/Event/PostResponseEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Allows to execute logic after a response was sent * * @author Jordi Boggiano */ class PostResponseEvent extends Event { /** * The kernel in which this event was thrown * @var HttpKernelInterface */ private $kernel; private $request; private $response; public function __construct(HttpKernelInterface $kernel, Request $request, Response $response) { $this->kernel = $kernel; $this->request = $request; $this->response = $response; } /** * Returns the kernel in which this event was thrown. * * @return HttpKernelInterface */ public function getKernel() { return $this->kernel; } /** * Returns the request for which this event was thrown. * * @return Request */ public function getRequest() { return $this->request; } /** * Returns the response for which this event was thrown. * * @return Response */ public function getResponse() { return $this->response; } } PK]}x HttpKernel/Event/KernelEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\Event; /** * Base class for events thrown in the HttpKernel component * * @author Bernhard Schussek * * @api */ class KernelEvent extends Event { /** * The kernel in which this event was thrown * @var HttpKernelInterface */ private $kernel; /** * The request the kernel is currently processing * @var Request */ private $request; /** * The request type the kernel is currently processing. One of * HttpKernelInterface::MASTER_REQUEST and HttpKernelInterface::SUB_REQUEST * @var integer */ private $requestType; public function __construct(HttpKernelInterface $kernel, Request $request, $requestType) { $this->kernel = $kernel; $this->request = $request; $this->requestType = $requestType; } /** * Returns the kernel in which this event was thrown * * @return HttpKernelInterface * * @api */ public function getKernel() { return $this->kernel; } /** * Returns the request the kernel is currently processing * * @return Request * * @api */ public function getRequest() { return $this->request; } /** * Returns the request type the kernel is currently processing * * @return integer One of HttpKernelInterface::MASTER_REQUEST and * HttpKernelInterface::SUB_REQUEST * * @api */ public function getRequestType() { return $this->requestType; } /** * Checks if this is a master request. * * @return Boolean True if the request is a master request * * @api */ public function isMasterRequest() { return HttpKernelInterface::MASTER_REQUEST === $this->requestType; } } PK] 7'HttpKernel/Event/FinishRequestEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; /** * Triggered whenever a request is fully processed. * * @author Benjamin Eberlei */ class FinishRequestEvent extends KernelEvent { } PK]9I%HttpKernel/Event/GetResponseEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpFoundation\Response; /** * Allows to create a response for a request * * Call setResponse() to set the response that will be returned for the * current request. The propagation of this event is stopped as soon as a * response is set. * * @author Bernhard Schussek * * @api */ class GetResponseEvent extends KernelEvent { /** * The response object * @var Response */ private $response; /** * Returns the response object * * @return Response * * @api */ public function getResponse() { return $this->response; } /** * Sets a response and stops event propagation * * @param Response $response * * @api */ public function setResponse(Response $response) { $this->response = $response; $this->stopPropagation(); } /** * Returns whether a response was set * * @return Boolean Whether a response was set * * @api */ public function hasResponse() { return null !== $this->response; } } PK]`g(HttpKernel/Event/FilterResponseEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Allows to filter a Response object * * You can call getResponse() to retrieve the current response. With * setResponse() you can set a new response that will be returned to the * browser. * * @author Bernhard Schussek * * @api */ class FilterResponseEvent extends KernelEvent { /** * The current response object * @var Response */ private $response; public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, Response $response) { parent::__construct($kernel, $request, $requestType); $this->setResponse($response); } /** * Returns the current response object * * @return Response * * @api */ public function getResponse() { return $this->response; } /** * Sets a new response object * * @param Response $response * * @api */ public function setResponse(Response $response) { $this->response = $response; } } PK]ST)HttpKernel/Exception/FlattenException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException; /** * FlattenException wraps a PHP Exception to be able to serialize it. * * Basically, this class removes all objects from the trace. * * @author Fabien Potencier * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead. */ class FlattenException extends DebugFlattenException { } PK]+;XX8HttpKernel/Exception/ServiceUnavailableHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * ServiceUnavailableHttpException. * * @author Ben Ramsey */ class ServiceUnavailableHttpException extends HttpException { /** * Constructor. * * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0) { $headers = array(); if ($retryAfter) { $headers = array('Retry-After' => $retryAfter); } parent::__construct(503, $message, $previous, $headers, $code); } } PK];COO8HttpKernel/Exception/PreconditionFailedHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * PreconditionFailedHttpException. * * @author Ben Ramsey */ class PreconditionFailedHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(412, $message, $previous, array(), $code); } } PK]+~~:HttpKernel/Exception/PreconditionRequiredHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * PreconditionRequiredHttpException. * * @author Ben Ramsey * @see http://tools.ietf.org/html/rfc6585 */ class PreconditionRequiredHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(428, $message, $previous, array(), $code); } } PK]C%؝SS:HttpKernel/Exception/UnsupportedMediaTypeHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * UnsupportedMediaTypeHttpException. * * @author Ben Ramsey */ class UnsupportedMediaTypeHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(415, $message, $previous, array(), $code); } } PK]<~6HttpKernel/Exception/MethodNotAllowedHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * MethodNotAllowedHttpException. * * @author Kris Wallsmith */ class MethodNotAllowedHttpException extends HttpException { /** * Constructor. * * @param array $allow An array of allowed methods * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct(array $allow, $message = null, \Exception $previous = null, $code = 0) { $headers = array('Allow' => strtoupper(implode(', ', $allow))); parent::__construct(405, $message, $previous, $headers, $code); } } PK])8*uu2HttpKernel/Exception/AccessDeniedHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * AccessDeniedHttpException. * * @author Fabien Potencier * @author Christophe Coevoet */ class AccessDeniedHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(403, $message, $previous, array(), $code); } } PK]^,HttpKernel/Exception/FatalErrorException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; use Symfony\Component\Debug\Exception\FatalErrorException as DebugFatalErrorException; /** * Fatal Error Exception. * * @author Konstanton Myakshin * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead. */ class FatalErrorException extends DebugFatalErrorException { } PK]EE3HttpKernel/Exception/NotAcceptableHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * NotAcceptableHttpException. * * @author Ben Ramsey */ class NotAcceptableHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(406, $message, $previous, array(), $code); } } PK]瞻??.HttpKernel/Exception/NotFoundHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * NotFoundHttpException. * * @author Fabien Potencier */ class NotFoundHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(404, $message, $previous, array(), $code); } } PK][G??0HttpKernel/Exception/BadRequestHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * BadRequestHttpException. * * @author Ben Ramsey */ class BadRequestHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(400, $message, $previous, array(), $code); } } PK]rQrW/HttpKernel/Exception/HttpExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * Interface for HTTP error exceptions. * * @author Kris Wallsmith */ interface HttpExceptionInterface { /** * Returns the status code. * * @return integer An HTTP response status code */ public function getStatusCode(); /** * Returns response headers. * * @return array Response headers */ public function getHeaders(); } PK]*2HttpKernel/Exception/UnauthorizedHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * UnauthorizedHttpException. * * @author Ben Ramsey */ class UnauthorizedHttpException extends HttpException { /** * Constructor. * * @param string $challenge WWW-Authenticate challenge string * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($challenge, $message = null, \Exception $previous = null, $code = 0) { $headers = array('WWW-Authenticate' => $challenge); parent::__construct(401, $message, $previous, $headers, $code); } } PK]N0;;.HttpKernel/Exception/ConflictHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * ConflictHttpException. * * @author Ben Ramsey */ class ConflictHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(409, $message, $previous, array(), $code); } } PK] GG4HttpKernel/Exception/LengthRequiredHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * LengthRequiredHttpException. * * @author Ben Ramsey */ class LengthRequiredHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(411, $message, $previous, array(), $code); } } PK]Ѕ33*HttpKernel/Exception/GoneHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * GoneHttpException. * * @author Ben Ramsey */ class GoneHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(410, $message, $previous, array(), $code); } } PK]75HttpKernel/Exception/TooManyRequestsHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * TooManyRequestsHttpException. * * @author Ben Ramsey * @see http://tools.ietf.org/html/rfc6585 */ class TooManyRequestsHttpException extends HttpException { /** * Constructor. * * @param integer|string $retryAfter The number of seconds or HTTP-date after which the request may be retried * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0) { $headers = array(); if ($retryAfter) { $headers = array('Retry-After' => $retryAfter); } parent::__construct(429, $message, $previous, $headers, $code); } } PK]W1d&HttpKernel/Exception/HttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * HttpException. * * @author Kris Wallsmith */ class HttpException extends \RuntimeException implements HttpExceptionInterface { private $statusCode; private $headers; public function __construct($statusCode, $message = null, \Exception $previous = null, array $headers = array(), $code = 0) { $this->statusCode = $statusCode; $this->headers = $headers; parent::__construct($message, $code, $previous); } public function getStatusCode() { return $this->statusCode; } public function getHeaders() { return $this->headers; } } PK] -HttpKernel/EventListener/FragmentListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\IpUtils; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\UriSigner; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Handles content fragments represented by special URIs. * * All URL paths starting with /_fragment are handled as * content fragments by this listener. * * If the request does not come from a trusted IP, it throws an * AccessDeniedHttpException exception. * * @author Fabien Potencier */ class FragmentListener implements EventSubscriberInterface { private $signer; private $fragmentPath; /** * Constructor. * * @param UriSigner $signer A UriSigner instance * @param string $fragmentPath The path that triggers this listener */ public function __construct(UriSigner $signer, $fragmentPath = '/_fragment') { $this->signer = $signer; $this->fragmentPath = $fragmentPath; } /** * Fixes request attributes when the path is '/_fragment'. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws AccessDeniedHttpException if the request does not come from a trusted IP. */ public function onKernelRequest(GetResponseEvent $event) { $request = $event->getRequest(); if ($this->fragmentPath !== rawurldecode($request->getPathInfo())) { return; } $this->validateRequest($request); parse_str($request->query->get('_path', ''), $attributes); $request->attributes->add($attributes); $request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', array()), $attributes)); $request->query->remove('_path'); } protected function validateRequest(Request $request) { // is the Request safe? if (!$request->isMethodSafe()) { throw new AccessDeniedHttpException(); } // does the Request come from a trusted IP? $trustedIps = array_merge($this->getLocalIpAddresses(), $request->getTrustedProxies()); $remoteAddress = $request->server->get('REMOTE_ADDR'); if (IpUtils::checkIp($remoteAddress, $trustedIps)) { return; } // is the Request signed? // we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering) if ($this->signer->check($request->getSchemeAndHttpHost().$request->getBaseUrl().$request->getPathInfo().(null !== ($qs = $request->server->get('QUERY_STRING')) ? '?'.$qs : ''))) { return; } throw new AccessDeniedHttpException(); } protected function getLocalIpAddresses() { return array('127.0.0.1', 'fe80::1', '::1'); } public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array(array('onKernelRequest', 48)), ); } } PK]S "P P +HttpKernel/EventListener/LocaleListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\RequestContextAwareInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Initializes the locale based on the current request. * * This listener works in 2 modes: * * * 2.3 compatibility mode where you must call setRequest whenever the Request changes. * * 2.4+ mode where you must pass a RequestStack instance in the constructor. * * @author Fabien Potencier */ class LocaleListener implements EventSubscriberInterface { private $router; private $defaultLocale; private $requestStack; /** * RequestStack will become required in 3.0. */ public function __construct($defaultLocale = 'en', RequestContextAwareInterface $router = null, RequestStack $requestStack = null) { $this->defaultLocale = $defaultLocale; $this->requestStack = $requestStack; $this->router = $router; } /** * Sets the current Request. * * This method was used to synchronize the Request, but as the HttpKernel * is doing that automatically now, you should never call it directly. * It is kept public for BC with the 2.3 version. * * @param Request|null $request A Request instance * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function setRequest(Request $request = null) { if (null === $request) { return; } $this->setLocale($request); $this->setRouterContext($request); } public function onKernelRequest(GetResponseEvent $event) { $request = $event->getRequest(); $request->setDefaultLocale($this->defaultLocale); $this->setLocale($request); $this->setRouterContext($request); } public function onKernelFinishRequest(FinishRequestEvent $event) { if (null === $this->requestStack) { return; // removed when requestStack is required } if (null !== $parentRequest = $this->requestStack->getParentRequest()) { $this->setRouterContext($parentRequest); } } private function setLocale(Request $request) { if ($locale = $request->attributes->get('_locale')) { $request->setLocale($locale); } } private function setRouterContext(Request $request) { if (null !== $this->router) { $this->router->getContext()->setParameter('_locale', $request->getLocale()); } } public static function getSubscribedEvents() { return array( // must be registered after the Router to have access to the _locale KernelEvents::REQUEST => array(array('onKernelRequest', 16)), KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)), ); } } PK]$$5HttpKernel/EventListener/StreamedResponseListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * StreamedResponseListener is responsible for sending the Response * to the client. * * @author Fabien Potencier */ class StreamedResponseListener implements EventSubscriberInterface { /** * Filters the Response. * * @param FilterResponseEvent $event A FilterResponseEvent instance */ public function onKernelResponse(FilterResponseEvent $event) { if (!$event->isMasterRequest()) { return; } $response = $event->getResponse(); if ($response instanceof StreamedResponse) { $response->send(); } } public static function getSubscribedEvents() { return array( KernelEvents::RESPONSE => array('onKernelResponse', -1024), ); } } PK] .HttpKernel/EventListener/ExceptionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Exception\FlattenException; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * ExceptionListener. * * @author Fabien Potencier */ class ExceptionListener implements EventSubscriberInterface { protected $controller; protected $logger; public function __construct($controller, LoggerInterface $logger = null) { $this->controller = $controller; $this->logger = $logger; } public function onKernelException(GetResponseForExceptionEvent $event) { static $handling; if (true === $handling) { return false; } $handling = true; $exception = $event->getException(); $request = $event->getRequest(); $this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine())); $request = $this->duplicateRequest($exception, $request); try { $response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, true); } catch (\Exception $e) { $this->logException($exception, sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage()), false); // set handling to false otherwise it wont be able to handle further more $handling = false; // re-throw the exception from within HttpKernel as this is a catch-all return; } $event->setResponse($response); $handling = false; } public static function getSubscribedEvents() { return array( KernelEvents::EXCEPTION => array('onKernelException', -128), ); } /** * Logs an exception. * * @param \Exception $exception The original \Exception instance * @param string $message The error message to log * @param Boolean $original False when the handling of the exception thrown another exception */ protected function logException(\Exception $exception, $message, $original = true) { $isCritical = !$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500; $context = array('exception' => $exception); if (null !== $this->logger) { if ($isCritical) { $this->logger->critical($message, $context); } else { $this->logger->error($message, $context); } } elseif (!$original || $isCritical) { error_log($message); } } /** * Clones the request for the exception. * * @param \Exception $exception The thrown exception. * @param Request $request The original request. * * @return Request $request The cloned request. */ protected function duplicateRequest(\Exception $exception, Request $request) { $attributes = array( '_controller' => $this->controller, 'exception' => FlattenException::create($exception), 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, // keep for BC -- as $format can be an argument of the controller callable // see src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php // @deprecated in 2.4, to be removed in 3.0 'format' => $request->getRequestFormat(), ); $request = $request->duplicate(null, null, $attributes); $request->setMethod('GET'); return $request; } } PK]PCyy-HttpKernel/EventListener/ResponseListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * ResponseListener fixes the Response headers based on the Request. * * @author Fabien Potencier */ class ResponseListener implements EventSubscriberInterface { private $charset; public function __construct($charset) { $this->charset = $charset; } /** * Filters the Response. * * @param FilterResponseEvent $event A FilterResponseEvent instance */ public function onKernelResponse(FilterResponseEvent $event) { if (!$event->isMasterRequest()) { return; } $response = $event->getResponse(); if (null === $response->getCharset()) { $response->setCharset($this->charset); } $response->prepare($event->getRequest()); } public static function getSubscribedEvents() { return array( KernelEvents::RESPONSE => 'onKernelResponse', ); } } PK] --+HttpKernel/EventListener/RouterListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RequestContextAwareInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; /** * Initializes the context from the request and sets request attributes based on a matching route. * * This listener works in 2 modes: * * * 2.3 compatibility mode where you must call setRequest whenever the Request changes. * * 2.4+ mode where you must pass a RequestStack instance in the constructor. * * @author Fabien Potencier */ class RouterListener implements EventSubscriberInterface { private $matcher; private $context; private $logger; private $request; private $requestStack; /** * Constructor. * * RequestStack will become required in 3.0. * * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) * @param LoggerInterface|null $logger The logger * * @throws \InvalidArgumentException */ public function __construct($matcher, RequestContext $context = null, LoggerInterface $logger = null, RequestStack $requestStack = null) { if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); } if (null === $context && !$matcher instanceof RequestContextAwareInterface) { throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.'); } $this->matcher = $matcher; $this->context = $context ?: $matcher->getContext(); $this->requestStack = $requestStack; $this->logger = $logger; } /** * Sets the current Request. * * This method was used to synchronize the Request, but as the HttpKernel * is doing that automatically now, you should never call it directly. * It is kept public for BC with the 2.3 version. * * @param Request|null $request A Request instance * * @deprecated Deprecated since version 2.4, to be moved to a private function in 3.0. */ public function setRequest(Request $request = null) { if (null !== $request && $this->request !== $request) { $this->context->fromRequest($request); } $this->request = $request; } public function onKernelFinishRequest(FinishRequestEvent $event) { if (null === $this->requestStack) { return; // removed when requestStack is required } $this->setRequest($this->requestStack->getParentRequest()); } public function onKernelRequest(GetResponseEvent $event) { $request = $event->getRequest(); // initialize the context that is also used by the generator (assuming matcher and generator share the same context instance) // we call setRequest even if most of the time, it has already been done to keep compatibility // with frameworks which do not use the Symfony service container // when we have a RequestStack, no need to do it if (null !== $this->requestStack) { $this->setRequest($request); } if ($request->attributes->has('_controller')) { // routing is already done return; } // add attributes based on the request (routing) try { // matching a request is more powerful than matching a URL path + context, so try that first if ($this->matcher instanceof RequestMatcherInterface) { $parameters = $this->matcher->matchRequest($request); } else { $parameters = $this->matcher->match($request->getPathInfo()); } if (null !== $this->logger) { $this->logger->info(sprintf('Matched route "%s" (parameters: %s)', $parameters['_route'], $this->parametersToString($parameters))); } $request->attributes->add($parameters); unset($parameters['_route']); unset($parameters['_controller']); $request->attributes->set('_route_params', $parameters); } catch (ResourceNotFoundException $e) { $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo()); if ($referer = $request->headers->get('referer')) { $message .= sprintf(' (from "%s")', $referer); } throw new NotFoundHttpException($message, $e); } catch (MethodNotAllowedException $e) { $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getPathInfo(), implode(', ', $e->getAllowedMethods())); throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e); } } private function parametersToString(array $parameters) { $pieces = array(); foreach ($parameters as $key => $val) { $pieces[] = sprintf('"%s": "%s"', $key, (is_string($val) ? $val : json_encode($val))); } return implode(', ', $pieces); } public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array(array('onKernelRequest', 32)), KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)), ); } } PK]E^-HttpKernel/EventListener/ProfilerListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\PostResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Profiler\Profiler; use Symfony\Component\HttpFoundation\RequestMatcherInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * ProfilerListener collects data for the current request by listening to the onKernelResponse event. * * @author Fabien Potencier */ class ProfilerListener implements EventSubscriberInterface { protected $profiler; protected $matcher; protected $onlyException; protected $onlyMasterRequests; protected $exception; protected $requests = array(); protected $profiles; protected $requestStack; protected $parents; /** * Constructor. * * @param Profiler $profiler A Profiler instance * @param RequestMatcherInterface $matcher A RequestMatcher instance * @param Boolean $onlyException true if the profiler only collects data when an exception occurs, false otherwise * @param Boolean $onlyMasterRequests true if the profiler only collects data when the request is a master request, false otherwise */ public function __construct(Profiler $profiler, RequestMatcherInterface $matcher = null, $onlyException = false, $onlyMasterRequests = false, RequestStack $requestStack = null) { $this->profiler = $profiler; $this->matcher = $matcher; $this->onlyException = (Boolean) $onlyException; $this->onlyMasterRequests = (Boolean) $onlyMasterRequests; $this->profiles = new \SplObjectStorage(); $this->parents = new \SplObjectStorage(); $this->requestStack = $requestStack; } /** * Handles the onKernelException event. * * @param GetResponseForExceptionEvent $event A GetResponseForExceptionEvent instance */ public function onKernelException(GetResponseForExceptionEvent $event) { if ($this->onlyMasterRequests && !$event->isMasterRequest()) { return; } $this->exception = $event->getException(); } /** * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function onKernelRequest(GetResponseEvent $event) { if (null === $this->requestStack) { $this->requests[] = $event->getRequest(); } } /** * Handles the onKernelResponse event. * * @param FilterResponseEvent $event A FilterResponseEvent instance */ public function onKernelResponse(FilterResponseEvent $event) { $master = $event->isMasterRequest(); if ($this->onlyMasterRequests && !$master) { return; } if ($this->onlyException && null === $this->exception) { return; } $request = $event->getRequest(); $exception = $this->exception; $this->exception = null; if (null !== $this->matcher && !$this->matcher->matches($request)) { return; } if (!$profile = $this->profiler->collect($request, $event->getResponse(), $exception)) { return; } $this->profiles[$request] = $profile; if (null !== $this->requestStack) { $this->parents[$request] = $this->requestStack->getParentRequest(); } elseif (!$master) { // to be removed when requestStack is required array_pop($this->requests); $this->parents[$request] = end($this->requests); } } public function onKernelTerminate(PostResponseEvent $event) { // attach children to parents foreach ($this->profiles as $request) { // isset call should be removed when requestStack is required if (isset($this->parents[$request]) && null !== $parentRequest = $this->parents[$request]) { if (isset($this->profiles[$parentRequest])) { $this->profiles[$parentRequest]->addChild($this->profiles[$request]); } } } // save profiles foreach ($this->profiles as $request) { $this->profiler->saveProfile($this->profiles[$request]); } $this->profiles = new \SplObjectStorage(); $this->parents = new \SplObjectStorage(); $this->requests = array(); } public static function getSubscribedEvents() { return array( // kernel.request must be registered as early as possible to not break // when an exception is thrown in any other kernel.request listener KernelEvents::REQUEST => array('onKernelRequest', 1024), KernelEvents::RESPONSE => array('onKernelResponse', -100), KernelEvents::EXCEPTION => 'onKernelException', KernelEvents::TERMINATE => array('onKernelTerminate', -1024), ); } } PK]/)A A 0HttpKernel/EventListener/TestSessionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * TestSessionListener. * * Saves session in test environment. * * @author Bulat Shakirzyanov * @author Fabien Potencier */ abstract class TestSessionListener implements EventSubscriberInterface { public function onKernelRequest(GetResponseEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } // bootstrap the session $session = $this->getSession(); if (!$session) { return; } $cookies = $event->getRequest()->cookies; if ($cookies->has($session->getName())) { $session->setId($cookies->get($session->getName())); } } /** * Checks if session was initialized and saves if current request is master * Runs on 'kernel.response' in test environment * * @param FilterResponseEvent $event */ public function onKernelResponse(FilterResponseEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } $session = $event->getRequest()->getSession(); if ($session && $session->isStarted()) { $session->save(); $params = session_get_cookie_params(); $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'])); } } public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array('onKernelRequest', 192), KernelEvents::RESPONSE => array('onKernelResponse', -128), ); } /** * Gets the session object. * * @return SessionInterface|null A SessionInterface instance of null if no session is available */ abstract protected function getSession(); } PK]@S,HttpKernel/EventListener/SessionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Sets the session in the request. * * @author Johannes M. Schmitt */ abstract class SessionListener implements EventSubscriberInterface { public function onKernelRequest(GetResponseEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } $request = $event->getRequest(); $session = $this->getSession(); if (null === $session || $request->hasSession()) { return; } $request->setSession($session); } public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array('onKernelRequest', 128), ); } /** * Gets the session object. * * @return SessionInterface|null A SessionInterface instance of null if no session is available */ abstract protected function getSession(); } PK]|$1HttpKernel/EventListener/ErrorsLoggerListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Debug\ErrorHandler; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\KernelEvents; /** * Injects the logger into the ErrorHandler, so that it can log various errors. * * @author Colin Frei * @author Konstantin Myakshin */ class ErrorsLoggerListener implements EventSubscriberInterface { private $channel; private $logger; public function __construct($channel, LoggerInterface $logger = null) { $this->channel = $channel; $this->logger = $logger; } public function injectLogger() { if (null !== $this->logger) { ErrorHandler::setLogger($this->logger, $this->channel); } } public static function getSubscribedEvents() { return array(KernelEvents::REQUEST => 'injectLogger'); } } PK]^(HttpKernel/EventListener/EsiListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\HttpCache\Esi; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * EsiListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for ESI. * * @author Fabien Potencier */ class EsiListener implements EventSubscriberInterface { private $esi; /** * Constructor. * * @param Esi $esi An ESI instance */ public function __construct(Esi $esi = null) { $this->esi = $esi; } /** * Filters the Response. * * @param FilterResponseEvent $event A FilterResponseEvent instance */ public function onKernelResponse(FilterResponseEvent $event) { if (!$event->isMasterRequest() || null === $this->esi) { return; } $this->esi->addSurrogateControl($event->getResponse()); } public static function getSubscribedEvents() { return array( KernelEvents::RESPONSE => 'onKernelResponse', ); } } PK]3a%HttpKernel/Bundle/BundleInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Bundle; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; /** * BundleInterface. * * @author Fabien Potencier * * @api */ interface BundleInterface extends ContainerAwareInterface { /** * Boots the Bundle. * * @api */ public function boot(); /** * Shutdowns the Bundle. * * @api */ public function shutdown(); /** * Builds the bundle. * * It is only ever called once when the cache is empty. * * @param ContainerBuilder $container A ContainerBuilder instance * * @api */ public function build(ContainerBuilder $container); /** * Returns the container extension that should be implicitly loaded. * * @return ExtensionInterface|null The default extension or null if there is none * * @api */ public function getContainerExtension(); /** * Returns the bundle name that this bundle overrides. * * Despite its name, this method does not imply any parent/child relationship * between the bundles, just a way to extend and override an existing * bundle. * * @return string The Bundle name it overrides or null if no parent * * @api */ public function getParent(); /** * Returns the bundle name (the class short name). * * @return string The Bundle name * * @api */ public function getName(); /** * Gets the Bundle namespace. * * @return string The Bundle namespace * * @api */ public function getNamespace(); /** * Gets the Bundle directory path. * * The path should always be returned as a Unix path (with /). * * @return string The Bundle absolute path * * @api */ public function getPath(); } PK]!llHttpKernel/Bundle/Bundle.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Bundle; use Symfony\Component\DependencyInjection\ContainerAware; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\Console\Application; use Symfony\Component\Finder\Finder; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; /** * An implementation of BundleInterface that adds a few conventions * for DependencyInjection extensions and Console commands. * * @author Fabien Potencier * * @api */ abstract class Bundle extends ContainerAware implements BundleInterface { protected $name; protected $extension; protected $path; /** * Boots the Bundle. */ public function boot() { } /** * Shutdowns the Bundle. */ public function shutdown() { } /** * Builds the bundle. * * It is only ever called once when the cache is empty. * * This method can be overridden to register compilation passes, * other extensions, ... * * @param ContainerBuilder $container A ContainerBuilder instance */ public function build(ContainerBuilder $container) { } /** * Returns the bundle's container extension. * * @return ExtensionInterface|null The container extension * * @throws \LogicException * * @api */ public function getContainerExtension() { if (null === $this->extension) { $basename = preg_replace('/Bundle$/', '', $this->getName()); $class = $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension'; if (class_exists($class)) { $extension = new $class(); // check naming convention $expectedAlias = Container::underscore($basename); if ($expectedAlias != $extension->getAlias()) { throw new \LogicException(sprintf( 'The extension alias for the default extension of a '. 'bundle must be the underscored version of the '. 'bundle name ("%s" instead of "%s")', $expectedAlias, $extension->getAlias() )); } $this->extension = $extension; } else { $this->extension = false; } } if ($this->extension) { return $this->extension; } } /** * Gets the Bundle namespace. * * @return string The Bundle namespace * * @api */ public function getNamespace() { $class = get_class($this); return substr($class, 0, strrpos($class, '\\')); } /** * Gets the Bundle directory path. * * @return string The Bundle absolute path * * @api */ public function getPath() { if (null === $this->path) { $reflected = new \ReflectionObject($this); $this->path = dirname($reflected->getFileName()); } return $this->path; } /** * Returns the bundle parent name. * * @return string The Bundle parent name it overrides or null if no parent * * @api */ public function getParent() { return null; } /** * Returns the bundle name (the class short name). * * @return string The Bundle name * * @api */ final public function getName() { if (null !== $this->name) { return $this->name; } $name = get_class($this); $pos = strrpos($name, '\\'); return $this->name = false === $pos ? $name : substr($name, $pos + 1); } /** * Finds and registers Commands. * * Override this method if your bundle commands do not follow the conventions: * * * Commands are in the 'Command' sub-directory * * Commands extend Symfony\Component\Console\Command\Command * * @param Application $application An Application instance */ public function registerCommands(Application $application) { if (!is_dir($dir = $this->getPath().'/Command')) { return; } $finder = new Finder(); $finder->files()->name('*Command.php')->in($dir); $prefix = $this->getNamespace().'\\Command'; foreach ($finder as $file) { $ns = $prefix; if ($relativePath = $file->getRelativePath()) { $ns .= '\\'.strtr($relativePath, '/', '\\'); } $class = $ns.'\\'.$file->getBasename('.php'); if ($this->container) { $alias = 'console.command.'.strtolower(str_replace('\\', '_', $class)); if ($this->container->has($alias)) { continue; } } $r = new \ReflectionClass($class); if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract() && !$r->getConstructor()->getNumberOfRequiredParameters()) { $application->add($r->newInstance()); } } } } PK]b b 'HttpKernel/HttpCache/StoreInterface.phpnu[ * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Interface implemented by HTTP cache stores. * * @author Fabien Potencier */ interface StoreInterface { /** * Locates a cached Response for the Request provided. * * @param Request $request A Request instance * * @return Response|null A Response instance, or null if no cache entry was found */ public function lookup(Request $request); /** * Writes a cache entry to the store for the given Request and Response. * * Existing entries are read and any that match the response are removed. This * method calls write with the new list of cache entries. * * @param Request $request A Request instance * @param Response $response A Response instance * * @return string The key under which the response is stored */ public function write(Request $request, Response $response); /** * Invalidates all cache entries that match the request. * * @param Request $request A Request instance */ public function invalidate(Request $request); /** * Locks the cache for a given Request. * * @param Request $request A Request instance * * @return Boolean|string true if the lock is acquired, the path to the current lock otherwise */ public function lock(Request $request); /** * Releases the lock for the given Request. * * @param Request $request A Request instance * * @return Boolean False if the lock file does not exist or cannot be unlocked, true otherwise */ public function unlock(Request $request); /** * Returns whether or not a lock exists. * * @param Request $request A Request instance * * @return Boolean true if lock exists, false otherwise */ public function isLocked(Request $request); /** * Purges data for the given URL. * * @param string $url A URL * * @return Boolean true if the URL exists and has been purged, false otherwise */ public function purge($url); /** * Cleanups storage. */ public function cleanup(); } PK]/) 1HttpKernel/HttpCache/EsiResponseCacheStrategy.phpnu[ * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Response; /** * EsiResponseCacheStrategy knows how to compute the Response cache HTTP header * based on the different ESI response cache headers. * * This implementation changes the master response TTL to the smallest TTL received * or force validation if one of the ESI has validation cache strategy. * * @author Fabien Potencier */ class EsiResponseCacheStrategy implements EsiResponseCacheStrategyInterface { private $cacheable = true; private $embeddedResponses = 0; private $ttls = array(); private $maxAges = array(); /** * {@inheritdoc} */ public function add(Response $response) { if ($response->isValidateable()) { $this->cacheable = false; } else { $this->ttls[] = $response->getTtl(); $this->maxAges[] = $response->getMaxAge(); } $this->embeddedResponses++; } /** * {@inheritdoc} */ public function update(Response $response) { // if we have no embedded Response, do nothing if (0 === $this->embeddedResponses) { return; } // Remove validation related headers in order to avoid browsers using // their own cache, because some of the response content comes from // at least one embedded response (which likely has a different caching strategy). if ($response->isValidateable()) { $response->setEtag(null); $response->setLastModified(null); $this->cacheable = false; } if (!$this->cacheable) { $response->headers->set('Cache-Control', 'no-cache, must-revalidate'); return; } $this->ttls[] = $response->getTtl(); $this->maxAges[] = $response->getMaxAge(); if (null !== $maxAge = min($this->maxAges)) { $response->setSharedMaxAge($maxAge); $response->headers->set('Age', $maxAge - min($this->ttls)); } $response->setMaxAge(0); } } PK]#[["HttpKernel/HttpCache/HttpCache.phpnu[ * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\TerminableInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Cache provides HTTP caching. * * @author Fabien Potencier * * @api */ class HttpCache implements HttpKernelInterface, TerminableInterface { private $kernel; private $store; private $request; private $esi; private $esiCacheStrategy; private $options = array(); private $traces = array(); /** * Constructor. * * The available options are: * * * debug: If true, the traces are added as a HTTP header to ease debugging * * * default_ttl The number of seconds that a cache entry should be considered * fresh when no explicit freshness information is provided in * a response. Explicit Cache-Control or Expires headers * override this value. (default: 0) * * * private_headers Set of request headers that trigger "private" cache-control behavior * on responses that don't explicitly state whether the response is * public or private via a Cache-Control directive. (default: Authorization and Cookie) * * * allow_reload Specifies whether the client can force a cache reload by including a * Cache-Control "no-cache" directive in the request. Set it to ``true`` * for compliance with RFC 2616. (default: false) * * * allow_revalidate Specifies whether the client can force a cache revalidate by including * a Cache-Control "max-age=0" directive in the request. Set it to ``true`` * for compliance with RFC 2616. (default: false) * * * stale_while_revalidate Specifies the default number of seconds (the granularity is the second as the * Response TTL precision is a second) during which the cache can immediately return * a stale response while it revalidates it in the background (default: 2). * This setting is overridden by the stale-while-revalidate HTTP Cache-Control * extension (see RFC 5861). * * * stale_if_error Specifies the default number of seconds (the granularity is the second) during which * the cache can serve a stale response when an error is encountered (default: 60). * This setting is overridden by the stale-if-error HTTP Cache-Control extension * (see RFC 5861). * * @param HttpKernelInterface $kernel An HttpKernelInterface instance * @param StoreInterface $store A Store instance * @param Esi $esi An Esi instance * @param array $options An array of options */ public function __construct(HttpKernelInterface $kernel, StoreInterface $store, Esi $esi = null, array $options = array()) { $this->store = $store; $this->kernel = $kernel; $this->esi = $esi; // needed in case there is a fatal error because the backend is too slow to respond register_shutdown_function(array($this->store, 'cleanup')); $this->options = array_merge(array( 'debug' => false, 'default_ttl' => 0, 'private_headers' => array('Authorization', 'Cookie'), 'allow_reload' => false, 'allow_revalidate' => false, 'stale_while_revalidate' => 2, 'stale_if_error' => 60, ), $options); } /** * Gets the current store. * * @return StoreInterface $store A StoreInterface instance */ public function getStore() { return $this->store; } /** * Returns an array of events that took place during processing of the last request. * * @return array An array of events */ public function getTraces() { return $this->traces; } /** * Returns a log message for the events of the last request processing. * * @return string A log message */ public function getLog() { $log = array(); foreach ($this->traces as $request => $traces) { $log[] = sprintf('%s: %s', $request, implode(', ', $traces)); } return implode('; ', $log); } /** * Gets the Request instance associated with the master request. * * @return Request A Request instance */ public function getRequest() { return $this->request; } /** * Gets the Kernel instance * * @return HttpKernelInterface An HttpKernelInterface instance */ public function getKernel() { return $this->kernel; } /** * Gets the Esi instance * * @return Esi An Esi instance */ public function getEsi() { return $this->esi; } /** * {@inheritdoc} * * @api */ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { // FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism if (HttpKernelInterface::MASTER_REQUEST === $type) { $this->traces = array(); $this->request = $request; if (null !== $this->esi) { $this->esiCacheStrategy = $this->esi->createCacheStrategy(); } } $path = $request->getPathInfo(); if ($qs = $request->getQueryString()) { $path .= '?'.$qs; } $this->traces[$request->getMethod().' '.$path] = array(); if (!$request->isMethodSafe()) { $response = $this->invalidate($request, $catch); } elseif ($request->headers->has('expect')) { $response = $this->pass($request, $catch); } else { $response = $this->lookup($request, $catch); } $this->restoreResponseBody($request, $response); $response->setDate(new \DateTime(null, new \DateTimeZone('UTC'))); if (HttpKernelInterface::MASTER_REQUEST === $type && $this->options['debug']) { $response->headers->set('X-Symfony-Cache', $this->getLog()); } if (null !== $this->esi) { if (HttpKernelInterface::MASTER_REQUEST === $type) { $this->esiCacheStrategy->update($response); } else { $this->esiCacheStrategy->add($response); } } $response->prepare($request); $response->isNotModified($request); return $response; } /** * {@inheritdoc} * * @api */ public function terminate(Request $request, Response $response) { if ($this->getKernel() instanceof TerminableInterface) { $this->getKernel()->terminate($request, $response); } } /** * Forwards the Request to the backend without storing the Response in the cache. * * @param Request $request A Request instance * @param Boolean $catch Whether to process exceptions * * @return Response A Response instance */ protected function pass(Request $request, $catch = false) { $this->record($request, 'pass'); return $this->forward($request, $catch); } /** * Invalidates non-safe methods (like POST, PUT, and DELETE). * * @param Request $request A Request instance * @param Boolean $catch Whether to process exceptions * * @return Response A Response instance * * @throws \Exception * * @see RFC2616 13.10 */ protected function invalidate(Request $request, $catch = false) { $response = $this->pass($request, $catch); // invalidate only when the response is successful if ($response->isSuccessful() || $response->isRedirect()) { try { $this->store->invalidate($request, $catch); // As per the RFC, invalidate Location and Content-Location URLs if present foreach (array('Location', 'Content-Location') as $header) { if ($uri = $response->headers->get($header)) { $subRequest = Request::create($uri, 'get', array(), array(), array(), $request->server->all()); $this->store->invalidate($subRequest); } } $this->record($request, 'invalidate'); } catch (\Exception $e) { $this->record($request, 'invalidate-failed'); if ($this->options['debug']) { throw $e; } } } return $response; } /** * Lookups a Response from the cache for the given Request. * * When a matching cache entry is found and is fresh, it uses it as the * response without forwarding any request to the backend. When a matching * cache entry is found but is stale, it attempts to "validate" the entry with * the backend using conditional GET. When no matching cache entry is found, * it triggers "miss" processing. * * @param Request $request A Request instance * @param Boolean $catch whether to process exceptions * * @return Response A Response instance * * @throws \Exception */ protected function lookup(Request $request, $catch = false) { // if allow_reload and no-cache Cache-Control, allow a cache reload if ($this->options['allow_reload'] && $request->isNoCache()) { $this->record($request, 'reload'); return $this->fetch($request, $catch); } try { $entry = $this->store->lookup($request); } catch (\Exception $e) { $this->record($request, 'lookup-failed'); if ($this->options['debug']) { throw $e; } return $this->pass($request, $catch); } if (null === $entry) { $this->record($request, 'miss'); return $this->fetch($request, $catch); } if (!$this->isFreshEnough($request, $entry)) { $this->record($request, 'stale'); return $this->validate($request, $entry, $catch); } $this->record($request, 'fresh'); $entry->headers->set('Age', $entry->getAge()); return $entry; } /** * Validates that a cache entry is fresh. * * The original request is used as a template for a conditional * GET request with the backend. * * @param Request $request A Request instance * @param Response $entry A Response instance to validate * @param Boolean $catch Whether to process exceptions * * @return Response A Response instance */ protected function validate(Request $request, Response $entry, $catch = false) { $subRequest = clone $request; // send no head requests because we want content $subRequest->setMethod('GET'); // add our cached last-modified validator $subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified')); // Add our cached etag validator to the environment. // We keep the etags from the client to handle the case when the client // has a different private valid entry which is not cached here. $cachedEtags = $entry->getEtag() ? array($entry->getEtag()) : array(); $requestEtags = $request->getEtags(); if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) { $subRequest->headers->set('if_none_match', implode(', ', $etags)); } $response = $this->forward($subRequest, $catch, $entry); if (304 == $response->getStatusCode()) { $this->record($request, 'valid'); // return the response and not the cache entry if the response is valid but not cached $etag = $response->getEtag(); if ($etag && in_array($etag, $requestEtags) && !in_array($etag, $cachedEtags)) { return $response; } $entry = clone $entry; $entry->headers->remove('Date'); foreach (array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) { if ($response->headers->has($name)) { $entry->headers->set($name, $response->headers->get($name)); } } $response = $entry; } else { $this->record($request, 'invalid'); } if ($response->isCacheable()) { $this->store($request, $response); } return $response; } /** * Forwards the Request to the backend and determines whether the response should be stored. * * This methods is triggered when the cache missed or a reload is required. * * @param Request $request A Request instance * @param Boolean $catch whether to process exceptions * * @return Response A Response instance */ protected function fetch(Request $request, $catch = false) { $subRequest = clone $request; // send no head requests because we want content $subRequest->setMethod('GET'); // avoid that the backend sends no content $subRequest->headers->remove('if_modified_since'); $subRequest->headers->remove('if_none_match'); $response = $this->forward($subRequest, $catch); if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) { $response->setPrivate(true); } elseif ($this->options['default_ttl'] > 0 && null === $response->getTtl() && !$response->headers->getCacheControlDirective('must-revalidate')) { $response->setTtl($this->options['default_ttl']); } if ($response->isCacheable()) { $this->store($request, $response); } return $response; } /** * Forwards the Request to the backend and returns the Response. * * @param Request $request A Request instance * @param Boolean $catch Whether to catch exceptions or not * @param Response $entry A Response instance (the stale entry if present, null otherwise) * * @return Response A Response instance */ protected function forward(Request $request, $catch = false, Response $entry = null) { if ($this->esi) { $this->esi->addSurrogateEsiCapability($request); } // modify the X-Forwarded-For header if needed $forwardedFor = $request->headers->get('X-Forwarded-For'); if ($forwardedFor) { $request->headers->set('X-Forwarded-For', $forwardedFor.', '.$request->server->get('REMOTE_ADDR')); } else { $request->headers->set('X-Forwarded-For', $request->server->get('REMOTE_ADDR')); } // fix the client IP address by setting it to 127.0.0.1 as HttpCache // is always called from the same process as the backend. $request->server->set('REMOTE_ADDR', '127.0.0.1'); // always a "master" request (as the real master request can be in cache) $response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $catch); // FIXME: we probably need to also catch exceptions if raw === true // we don't implement the stale-if-error on Requests, which is nonetheless part of the RFC if (null !== $entry && in_array($response->getStatusCode(), array(500, 502, 503, 504))) { if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) { $age = $this->options['stale_if_error']; } if (abs($entry->getTtl()) < $age) { $this->record($request, 'stale-if-error'); return $entry; } } $this->processResponseBody($request, $response); return $response; } /** * Checks whether the cache entry is "fresh enough" to satisfy the Request. * * @param Request $request A Request instance * @param Response $entry A Response instance * * @return Boolean true if the cache entry if fresh enough, false otherwise */ protected function isFreshEnough(Request $request, Response $entry) { if (!$entry->isFresh()) { return $this->lock($request, $entry); } if ($this->options['allow_revalidate'] && null !== $maxAge = $request->headers->getCacheControlDirective('max-age')) { return $maxAge > 0 && $maxAge >= $entry->getAge(); } return true; } /** * Locks a Request during the call to the backend. * * @param Request $request A Request instance * @param Response $entry A Response instance * * @return Boolean true if the cache entry can be returned even if it is staled, false otherwise */ protected function lock(Request $request, Response $entry) { // try to acquire a lock to call the backend $lock = $this->store->lock($request, $entry); // there is already another process calling the backend if (true !== $lock) { // check if we can serve the stale entry if (null === $age = $entry->headers->getCacheControlDirective('stale-while-revalidate')) { $age = $this->options['stale_while_revalidate']; } if (abs($entry->getTtl()) < $age) { $this->record($request, 'stale-while-revalidate'); // server the stale response while there is a revalidation return true; } // wait for the lock to be released $wait = 0; while ($this->store->isLocked($request) && $wait < 5000000) { usleep(50000); $wait += 50000; } if ($wait < 2000000) { // replace the current entry with the fresh one $new = $this->lookup($request); $entry->headers = $new->headers; $entry->setContent($new->getContent()); $entry->setStatusCode($new->getStatusCode()); $entry->setProtocolVersion($new->getProtocolVersion()); foreach ($new->headers->getCookies() as $cookie) { $entry->headers->setCookie($cookie); } } else { // backend is slow as hell, send a 503 response (to avoid the dog pile effect) $entry->setStatusCode(503); $entry->setContent('503 Service Unavailable'); $entry->headers->set('Retry-After', 10); } return true; } // we have the lock, call the backend return false; } /** * Writes the Response to the cache. * * @param Request $request A Request instance * @param Response $response A Response instance * * @throws \Exception */ protected function store(Request $request, Response $response) { try { $this->store->write($request, $response); $this->record($request, 'store'); $response->headers->set('Age', $response->getAge()); } catch (\Exception $e) { $this->record($request, 'store-failed'); if ($this->options['debug']) { throw $e; } } // now that the response is cached, release the lock $this->store->unlock($request); } /** * Restores the Response body. * * @param Request $request A Request instance * @param Response $response A Response instance * * @return Response A Response instance */ private function restoreResponseBody(Request $request, Response $response) { if ($request->isMethod('HEAD') || 304 === $response->getStatusCode()) { $response->setContent(null); $response->headers->remove('X-Body-Eval'); $response->headers->remove('X-Body-File'); return; } if ($response->headers->has('X-Body-Eval')) { ob_start(); if ($response->headers->has('X-Body-File')) { include $response->headers->get('X-Body-File'); } else { eval('; ?>'.$response->getContent().'setContent(ob_get_clean()); $response->headers->remove('X-Body-Eval'); if (!$response->headers->has('Transfer-Encoding')) { $response->headers->set('Content-Length', strlen($response->getContent())); } } elseif ($response->headers->has('X-Body-File')) { $response->setContent(file_get_contents($response->headers->get('X-Body-File'))); } else { return; } $response->headers->remove('X-Body-File'); } protected function processResponseBody(Request $request, Response $response) { if (null !== $this->esi && $this->esi->needsEsiParsing($response)) { $this->esi->process($request, $response); } } /** * Checks if the Request includes authorization or other sensitive information * that should cause the Response to be considered private by default. * * @param Request $request A Request instance * * @return Boolean true if the Request is private, false otherwise */ private function isPrivateRequest(Request $request) { foreach ($this->options['private_headers'] as $key) { $key = strtolower(str_replace('HTTP_', '', $key)); if ('cookie' === $key) { if (count($request->cookies->all())) { return true; } } elseif ($request->headers->has($key)) { return true; } } return false; } /** * Records that an event took place. * * @param Request $request A Request instance * @param string $event The event name */ private function record(Request $request, $event) { $path = $request->getPathInfo(); if ($qs = $request->getQueryString()) { $path .= '?'.$qs; } $this->traces[$request->getMethod().' '.$path][] = $event; } } PK]K:11HttpKernel/HttpCache/Store.phpnu[ * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Store implements all the logic for storing cache metadata (Request and Response headers). * * @author Fabien Potencier */ class Store implements StoreInterface { protected $root; private $keyCache; private $locks; /** * Constructor. * * @param string $root The path to the cache directory */ public function __construct($root) { $this->root = $root; if (!is_dir($this->root)) { mkdir($this->root, 0777, true); } $this->keyCache = new \SplObjectStorage(); $this->locks = array(); } /** * Cleanups storage. */ public function cleanup() { // unlock everything foreach ($this->locks as $lock) { if (file_exists($lock)) { @unlink($lock); } } $error = error_get_last(); if (1 === $error['type'] && false === headers_sent()) { // send a 503 header('HTTP/1.0 503 Service Unavailable'); header('Retry-After: 10'); echo '503 Service Unavailable'; } } /** * Locks the cache for a given Request. * * @param Request $request A Request instance * * @return Boolean|string true if the lock is acquired, the path to the current lock otherwise */ public function lock(Request $request) { $path = $this->getPath($this->getCacheKey($request).'.lck'); if (!is_dir(dirname($path)) && false === @mkdir(dirname($path), 0777, true)) { return false; } $lock = @fopen($path, 'x'); if (false !== $lock) { fclose($lock); $this->locks[] = $path; return true; } return !file_exists($path) ?: $path; } /** * Releases the lock for the given Request. * * @param Request $request A Request instance * * @return Boolean False if the lock file does not exist or cannot be unlocked, true otherwise */ public function unlock(Request $request) { $file = $this->getPath($this->getCacheKey($request).'.lck'); return is_file($file) ? @unlink($file) : false; } public function isLocked(Request $request) { return is_file($this->getPath($this->getCacheKey($request).'.lck')); } /** * Locates a cached Response for the Request provided. * * @param Request $request A Request instance * * @return Response|null A Response instance, or null if no cache entry was found */ public function lookup(Request $request) { $key = $this->getCacheKey($request); if (!$entries = $this->getMetadata($key)) { return null; } // find a cached entry that matches the request. $match = null; foreach ($entries as $entry) { if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? $entry[1]['vary'][0] : '', $request->headers->all(), $entry[0])) { $match = $entry; break; } } if (null === $match) { return null; } list($req, $headers) = $match; if (is_file($body = $this->getPath($headers['x-content-digest'][0]))) { return $this->restoreResponse($headers, $body); } // TODO the metaStore referenced an entity that doesn't exist in // the entityStore. We definitely want to return nil but we should // also purge the entry from the meta-store when this is detected. return null; } /** * Writes a cache entry to the store for the given Request and Response. * * Existing entries are read and any that match the response are removed. This * method calls write with the new list of cache entries. * * @param Request $request A Request instance * @param Response $response A Response instance * * @return string The key under which the response is stored * * @throws \RuntimeException */ public function write(Request $request, Response $response) { $key = $this->getCacheKey($request); $storedEnv = $this->persistRequest($request); // write the response body to the entity store if this is the original response if (!$response->headers->has('X-Content-Digest')) { $digest = $this->generateContentDigest($response); if (false === $this->save($digest, $response->getContent())) { throw new \RuntimeException('Unable to store the entity.'); } $response->headers->set('X-Content-Digest', $digest); if (!$response->headers->has('Transfer-Encoding')) { $response->headers->set('Content-Length', strlen($response->getContent())); } } // read existing cache entries, remove non-varying, and add this one to the list $entries = array(); $vary = $response->headers->get('vary'); foreach ($this->getMetadata($key) as $entry) { if (!isset($entry[1]['vary'][0])) { $entry[1]['vary'] = array(''); } if ($vary != $entry[1]['vary'][0] || !$this->requestsMatch($vary, $entry[0], $storedEnv)) { $entries[] = $entry; } } $headers = $this->persistResponse($response); unset($headers['age']); array_unshift($entries, array($storedEnv, $headers)); if (false === $this->save($key, serialize($entries))) { throw new \RuntimeException('Unable to store the metadata.'); } return $key; } /** * Returns content digest for $response. * * @param Response $response * * @return string */ protected function generateContentDigest(Response $response) { return 'en'.hash('sha256', $response->getContent()); } /** * Invalidates all cache entries that match the request. * * @param Request $request A Request instance * * @throws \RuntimeException */ public function invalidate(Request $request) { $modified = false; $key = $this->getCacheKey($request); $entries = array(); foreach ($this->getMetadata($key) as $entry) { $response = $this->restoreResponse($entry[1]); if ($response->isFresh()) { $response->expire(); $modified = true; $entries[] = array($entry[0], $this->persistResponse($response)); } else { $entries[] = $entry; } } if ($modified) { if (false === $this->save($key, serialize($entries))) { throw new \RuntimeException('Unable to store the metadata.'); } } } /** * Determines whether two Request HTTP header sets are non-varying based on * the vary response header value provided. * * @param string $vary A Response vary header * @param array $env1 A Request HTTP header array * @param array $env2 A Request HTTP header array * * @return Boolean true if the two environments match, false otherwise */ private function requestsMatch($vary, $env1, $env2) { if (empty($vary)) { return true; } foreach (preg_split('/[\s,]+/', $vary) as $header) { $key = strtr(strtolower($header), '_', '-'); $v1 = isset($env1[$key]) ? $env1[$key] : null; $v2 = isset($env2[$key]) ? $env2[$key] : null; if ($v1 !== $v2) { return false; } } return true; } /** * Gets all data associated with the given key. * * Use this method only if you know what you are doing. * * @param string $key The store key * * @return array An array of data associated with the key */ private function getMetadata($key) { if (false === $entries = $this->load($key)) { return array(); } return unserialize($entries); } /** * Purges data for the given URL. * * @param string $url A URL * * @return Boolean true if the URL exists and has been purged, false otherwise */ public function purge($url) { if (is_file($path = $this->getPath($this->getCacheKey(Request::create($url))))) { unlink($path); return true; } return false; } /** * Loads data for the given key. * * @param string $key The store key * * @return string The data associated with the key */ private function load($key) { $path = $this->getPath($key); return is_file($path) ? file_get_contents($path) : false; } /** * Save data for the given key. * * @param string $key The store key * @param string $data The data to store * * @return Boolean */ private function save($key, $data) { $path = $this->getPath($key); if (!is_dir(dirname($path)) && false === @mkdir(dirname($path), 0777, true)) { return false; } $tmpFile = tempnam(dirname($path), basename($path)); if (false === $fp = @fopen($tmpFile, 'wb')) { return false; } @fwrite($fp, $data); @fclose($fp); if ($data != file_get_contents($tmpFile)) { return false; } if (false === @rename($tmpFile, $path)) { return false; } @chmod($path, 0666 & ~umask()); } public function getPath($key) { return $this->root.DIRECTORY_SEPARATOR.substr($key, 0, 2).DIRECTORY_SEPARATOR.substr($key, 2, 2).DIRECTORY_SEPARATOR.substr($key, 4, 2).DIRECTORY_SEPARATOR.substr($key, 6); } /** * Generates a cache key for the given Request. * * This method should return a key that must only depend on a * normalized version of the request URI. * * If the same URI can have more than one representation, based on some * headers, use a Vary header to indicate them, and each representation will * be stored independently under the same cache key. * * @param Request $request A Request instance * * @return string A key for the given Request */ protected function generateCacheKey(Request $request) { return 'md'.hash('sha256', $request->getUri()); } /** * Returns a cache key for the given Request. * * @param Request $request A Request instance * * @return string A key for the given Request */ private function getCacheKey(Request $request) { if (isset($this->keyCache[$request])) { return $this->keyCache[$request]; } return $this->keyCache[$request] = $this->generateCacheKey($request); } /** * Persists the Request HTTP headers. * * @param Request $request A Request instance * * @return array An array of HTTP headers */ private function persistRequest(Request $request) { return $request->headers->all(); } /** * Persists the Response HTTP headers. * * @param Response $response A Response instance * * @return array An array of HTTP headers */ private function persistResponse(Response $response) { $headers = $response->headers->all(); $headers['X-Status'] = array($response->getStatusCode()); return $headers; } /** * Restores a Response from the HTTP headers and body. * * @param array $headers An array of HTTP headers for the Response * @param string $body The Response body * * @return Response */ private function restoreResponse($headers, $body = null) { $status = $headers['X-Status'][0]; unset($headers['X-Status']); if (null !== $body) { $headers['X-Body-File'] = array($body); } return new Response($body, $status, $headers); } } PK]wn n HttpKernel/HttpCache/Esi.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Esi implements the ESI capabilities to Request and Response instances. * * For more information, read the following W3C notes: * * * ESI Language Specification 1.0 (http://www.w3.org/TR/esi-lang) * * * Edge Architecture Specification (http://www.w3.org/TR/edge-arch) * * @author Fabien Potencier */ class Esi { private $contentTypes; /** * Constructor. * * @param array $contentTypes An array of content-type that should be parsed for ESI information. * (default: text/html, text/xml, application/xhtml+xml, and application/xml) */ public function __construct(array $contentTypes = array('text/html', 'text/xml', 'application/xhtml+xml', 'application/xml')) { $this->contentTypes = $contentTypes; } /** * Returns a new cache strategy instance. * * @return EsiResponseCacheStrategyInterface A EsiResponseCacheStrategyInterface instance */ public function createCacheStrategy() { return new EsiResponseCacheStrategy(); } /** * Checks that at least one surrogate has ESI/1.0 capability. * * @param Request $request A Request instance * * @return Boolean true if one surrogate has ESI/1.0 capability, false otherwise */ public function hasSurrogateEsiCapability(Request $request) { if (null === $value = $request->headers->get('Surrogate-Capability')) { return false; } return false !== strpos($value, 'ESI/1.0'); } /** * Adds ESI/1.0 capability to the given Request. * * @param Request $request A Request instance */ public function addSurrogateEsiCapability(Request $request) { $current = $request->headers->get('Surrogate-Capability'); $new = 'symfony2="ESI/1.0"'; $request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new); } /** * Adds HTTP headers to specify that the Response needs to be parsed for ESI. * * This method only adds an ESI HTTP header if the Response has some ESI tags. * * @param Response $response A Response instance */ public function addSurrogateControl(Response $response) { if (false !== strpos($response->getContent(), 'headers->set('Surrogate-Control', 'content="ESI/1.0"'); } } /** * Checks that the Response needs to be parsed for ESI tags. * * @param Response $response A Response instance * * @return Boolean true if the Response needs to be parsed, false otherwise */ public function needsEsiParsing(Response $response) { if (!$control = $response->headers->get('Surrogate-Control')) { return false; } return (Boolean) preg_match('#content="[^"]*ESI/1.0[^"]*"#', $control); } /** * Renders an ESI tag. * * @param string $uri A URI * @param string $alt An alternate URI * @param Boolean $ignoreErrors Whether to ignore errors or not * @param string $comment A comment to add as an esi:include tag * * @return string */ public function renderIncludeTag($uri, $alt = null, $ignoreErrors = true, $comment = '') { $html = sprintf('', $uri, $ignoreErrors ? ' onerror="continue"' : '', $alt ? sprintf(' alt="%s"', $alt) : '' ); if (!empty($comment)) { return sprintf("\n%s", $comment, $html); } return $html; } /** * Replaces a Response ESI tags with the included resource content. * * @param Request $request A Request instance * @param Response $response A Response instance * * @return Response */ public function process(Request $request, Response $response) { $this->request = $request; $type = $response->headers->get('Content-Type'); if (empty($type)) { $type = 'text/html'; } $parts = explode(';', $type); if (!in_array($parts[0], $this->contentTypes)) { return $response; } // we don't use a proper XML parser here as we can have ESI tags in a plain text response $content = $response->getContent(); $content = str_replace(array('', ''), $content); $content = preg_replace_callback('##', array($this, 'handleEsiIncludeTag'), $content); $content = preg_replace('#]*(?:/|#', '', $content); $content = preg_replace('#.*?#', '', $content); $response->setContent($content); $response->headers->set('X-Body-Eval', 'ESI'); // remove ESI/1.0 from the Surrogate-Control header if ($response->headers->has('Surrogate-Control')) { $value = $response->headers->get('Surrogate-Control'); if ('content="ESI/1.0"' == $value) { $response->headers->remove('Surrogate-Control'); } elseif (preg_match('#,\s*content="ESI/1.0"#', $value)) { $response->headers->set('Surrogate-Control', preg_replace('#,\s*content="ESI/1.0"#', '', $value)); } elseif (preg_match('#content="ESI/1.0",\s*#', $value)) { $response->headers->set('Surrogate-Control', preg_replace('#content="ESI/1.0",\s*#', '', $value)); } } } /** * Handles an ESI from the cache. * * @param HttpCache $cache An HttpCache instance * @param string $uri The main URI * @param string $alt An alternative URI * @param Boolean $ignoreErrors Whether to ignore errors or not * * @return string * * @throws \RuntimeException * @throws \Exception */ public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors) { $subRequest = Request::create($uri, 'get', array(), $cache->getRequest()->cookies->all(), array(), $cache->getRequest()->server->all()); try { $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); if (!$response->isSuccessful()) { throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode())); } return $response->getContent(); } catch (\Exception $e) { if ($alt) { return $this->handle($cache, $alt, '', $ignoreErrors); } if (!$ignoreErrors) { throw $e; } } } /** * Handles an ESI include tag (called internally). * * @param array $attributes An array containing the attributes. * * @return string The response content for the include. * * @throws \RuntimeException */ private function handleEsiIncludeTag($attributes) { $options = array(); preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $attributes[1], $matches, PREG_SET_ORDER); foreach ($matches as $set) { $options[$set[1]] = $set[2]; } if (!isset($options['src'])) { throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.'); } return sprintf('esi->handle($this, \'%s\', \'%s\', %s) ?>'."\n", $options['src'], isset($options['alt']) ? $options['alt'] : null, isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false' ); } } PK]M~CC:HttpKernel/HttpCache/EsiResponseCacheStrategyInterface.phpnu[ * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Response; /** * EsiResponseCacheStrategyInterface implementations know how to compute the * Response cache HTTP header based on the different ESI response cache headers. * * @author Fabien Potencier */ interface EsiResponseCacheStrategyInterface { /** * Adds a Response. * * @param Response $response */ public function add(Response $response); /** * Updates the Response HTTP headers based on the embedded Responses. * * @param Response $response */ public function update(Response $response); } PK]xXX-HttpKernel/Controller/ControllerReference.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; /** * Acts as a marker and a data holder for a Controller. * * Some methods in Symfony accept both a URI (as a string) or a controller as * an argument. In the latter case, instead of passing an array representing * the controller, you can use an instance of this class. * * @author Fabien Potencier * * @see Symfony\Component\HttpKernel\FragmentRenderer * @see Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface */ class ControllerReference { public $controller; public $attributes = array(); public $query = array(); /** * Constructor. * * @param string $controller The controller name * @param array $attributes An array of parameters to add to the Request attributes * @param array $query An array of parameters to add to the Request query string */ public function __construct($controller, array $attributes = array(), array $query = array()) { $this->controller = $controller; $this->attributes = $attributes; $this->query = $query; } } PK]^/|Goo5HttpKernel/Controller/ControllerResolverInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\HttpFoundation\Request; /** * A ControllerResolverInterface implementation knows how to determine the * controller to execute based on a Request object. * * It can also determine the arguments to pass to the Controller. * * A Controller can be any valid PHP callable. * * @author Fabien Potencier * * @api */ interface ControllerResolverInterface { /** * Returns the Controller instance associated with a Request. * * As several resolvers can exist for a single application, a resolver must * return false when it is not able to determine the controller. * * The resolver must only throw an exception when it should be able to load * controller but cannot because of some errors made by the developer. * * @param Request $request A Request instance * * @return callable|false A PHP callable representing the Controller, * or false if this resolver is not able to determine the controller * * @throws \LogicException If the controller can't be found * * @api */ public function getController(Request $request); /** * Returns the arguments to pass to the controller. * * @param Request $request A Request instance * @param callable $controller A PHP callable * * @return array An array of arguments to pass to the controller * * @throws \RuntimeException When value for argument given is not provided * * @api */ public function getArguments(Request $request, $controller); } PK]|  5HttpKernel/Controller/TraceableControllerResolver.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\HttpFoundation\Request; /** * TraceableControllerResolver. * * @author Fabien Potencier */ class TraceableControllerResolver implements ControllerResolverInterface { private $resolver; private $stopwatch; /** * Constructor. * * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance * @param Stopwatch $stopwatch A Stopwatch instance */ public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch) { $this->resolver = $resolver; $this->stopwatch = $stopwatch; } /** * {@inheritdoc} */ public function getController(Request $request) { $e = $this->stopwatch->start('controller.get_callable'); $ret = $this->resolver->getController($request); $e->stop(); return $ret; } /** * {@inheritdoc} */ public function getArguments(Request $request, $controller) { $e = $this->stopwatch->start('controller.get_arguments'); $ret = $this->resolver->getArguments($request, $controller); $e->stop(); return $ret; } } PK]NCtt,HttpKernel/Controller/ControllerResolver.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; /** * ControllerResolver. * * This implementation uses the '_controller' request attribute to determine * the controller to execute and uses the request attributes to determine * the controller method arguments. * * @author Fabien Potencier * * @api */ class ControllerResolver implements ControllerResolverInterface { private $logger; /** * Constructor. * * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(LoggerInterface $logger = null) { $this->logger = $logger; } /** * {@inheritdoc} * * This method looks for a '_controller' request attribute that represents * the controller name (a string like ClassName::MethodName). * * @api */ public function getController(Request $request) { if (!$controller = $request->attributes->get('_controller')) { if (null !== $this->logger) { $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing'); } return false; } if (is_array($controller)) { return $controller; } if (is_object($controller)) { if (method_exists($controller, '__invoke')) { return $controller; } throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', get_class($controller), $request->getPathInfo())); } if (false === strpos($controller, ':')) { if (method_exists($controller, '__invoke')) { return new $controller(); } elseif (function_exists($controller)) { return $controller; } } $callable = $this->createController($controller); if (!is_callable($callable)) { throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', $controller, $request->getPathInfo())); } return $callable; } /** * {@inheritdoc} * * @api */ public function getArguments(Request $request, $controller) { if (is_array($controller)) { $r = new \ReflectionMethod($controller[0], $controller[1]); } elseif (is_object($controller) && !$controller instanceof \Closure) { $r = new \ReflectionObject($controller); $r = $r->getMethod('__invoke'); } else { $r = new \ReflectionFunction($controller); } return $this->doGetArguments($request, $controller, $r->getParameters()); } protected function doGetArguments(Request $request, $controller, array $parameters) { $attributes = $request->attributes->all(); $arguments = array(); foreach ($parameters as $param) { if (array_key_exists($param->name, $attributes)) { $arguments[] = $attributes[$param->name]; } elseif ($param->getClass() && $param->getClass()->isInstance($request)) { $arguments[] = $request; } elseif ($param->isDefaultValueAvailable()) { $arguments[] = $param->getDefaultValue(); } else { if (is_array($controller)) { $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]); } elseif (is_object($controller)) { $repr = get_class($controller); } else { $repr = $controller; } throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name)); } } return $arguments; } /** * Returns a callable for the given controller. * * @param string $controller A Controller string * * @return mixed A PHP callable * * @throws \InvalidArgumentException */ protected function createController($controller) { if (false === strpos($controller, '::')) { throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller)); } list($class, $method) = explode('::', $controller, 2); if (!class_exists($class)) { throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); } return array(new $class(), $method); } } PK]z TTHttpKernel/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver; use Symfony\Component\OptionsResolver\Exception\OptionDefinitionException; /** * Container for resolving inter-dependent options. * * @author Bernhard Schussek */ class Options implements \ArrayAccess, \Iterator, \Countable { /** * A list of option values. * @var array */ private $options = array(); /** * A list of normalizer closures. * @var array */ private $normalizers = array(); /** * A list of closures for evaluating lazy options. * @var array */ private $lazy = array(); /** * A list containing the currently locked options. * @var array */ private $lock = array(); /** * Whether at least one option has already been read. * * Once read, the options cannot be changed anymore. This is * necessary in order to avoid inconsistencies during the resolving * process. If any option is changed after being read, all evaluated * lazy options that depend on this option would become invalid. * * @var Boolean */ private $reading = false; /** * Sets the value of a given option. * * You can set lazy options by passing a closure with the following * signature: * * * function (Options $options) * * * This closure will be evaluated once the option is read using * {@link get()}. The closure has access to the resolved values of * other options through the passed {@link Options} instance. * * @param string $option The name of the option. * @param mixed $value The value of the option. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function set($option, $value) { // Setting is not possible once an option is read, because then lazy // options could manipulate the state of the object, leading to // inconsistent results. if ($this->reading) { throw new OptionDefinitionException('Options cannot be set anymore once options have been read.'); } // Setting is equivalent to overloading while discarding the previous // option value unset($this->options[$option]); unset($this->lazy[$option]); $this->overload($option, $value); } /** * Sets the normalizer for a given option. * * Normalizers should be closures with the following signature: * * * function (Options $options, $value) * * * This closure will be evaluated once the option is read using * {@link get()}. The closure has access to the resolved values of * other options through the passed {@link Options} instance. * * @param string $option The name of the option. * @param \Closure $normalizer The normalizer. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function setNormalizer($option, \Closure $normalizer) { if ($this->reading) { throw new OptionDefinitionException('Normalizers cannot be added anymore once options have been read.'); } $this->normalizers[$option] = $normalizer; } /** * Replaces the contents of the container with the given options. * * This method is a shortcut for {@link clear()} with subsequent * calls to {@link set()}. * * @param array $options The options to set. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function replace(array $options) { if ($this->reading) { throw new OptionDefinitionException('Options cannot be replaced anymore once options have been read.'); } $this->options = array(); $this->lazy = array(); $this->normalizers = array(); foreach ($options as $option => $value) { $this->overload($option, $value); } } /** * Overloads the value of a given option. * * Contrary to {@link set()}, this method keeps the previous default * value of the option so that you can access it if you pass a closure. * Passed closures should have the following signature: * * * function (Options $options, $value) * * * The second parameter passed to the closure is the current default * value of the option. * * @param string $option The option name. * @param mixed $value The option value. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function overload($option, $value) { if ($this->reading) { throw new OptionDefinitionException('Options cannot be overloaded anymore once options have been read.'); } // If an option is a closure that should be evaluated lazily, store it // in the "lazy" property. if ($value instanceof \Closure) { $reflClosure = new \ReflectionFunction($value); $params = $reflClosure->getParameters(); if (isset($params[0]) && null !== ($class = $params[0]->getClass()) && __CLASS__ === $class->name) { // Initialize the option if no previous value exists if (!isset($this->options[$option])) { $this->options[$option] = null; } // Ignore previous lazy options if the closure has no second parameter if (!isset($this->lazy[$option]) || !isset($params[1])) { $this->lazy[$option] = array(); } // Store closure for later evaluation $this->lazy[$option][] = $value; return; } } // Remove lazy options by default unset($this->lazy[$option]); $this->options[$option] = $value; } /** * Returns the value of the given option. * * If the option was a lazy option, it is evaluated now. * * @param string $option The option name. * * @return mixed The option value. * * @throws \OutOfBoundsException If the option does not exist. * @throws OptionDefinitionException If a cyclic dependency is detected * between two lazy options. */ public function get($option) { $this->reading = true; if (!array_key_exists($option, $this->options)) { throw new \OutOfBoundsException(sprintf('The option "%s" does not exist.', $option)); } if (isset($this->lazy[$option])) { $this->resolve($option); } if (isset($this->normalizers[$option])) { $this->normalize($option); } return $this->options[$option]; } /** * Returns whether the given option exists. * * @param string $option The option name. * * @return Boolean Whether the option exists. */ public function has($option) { return array_key_exists($option, $this->options); } /** * Removes the option with the given name. * * @param string $option The option name. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function remove($option) { if ($this->reading) { throw new OptionDefinitionException('Options cannot be removed anymore once options have been read.'); } unset($this->options[$option]); unset($this->lazy[$option]); unset($this->normalizers[$option]); } /** * Removes all options. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function clear() { if ($this->reading) { throw new OptionDefinitionException('Options cannot be cleared anymore once options have been read.'); } $this->options = array(); $this->lazy = array(); $this->normalizers = array(); } /** * Returns the values of all options. * * Lazy options are evaluated at this point. * * @return array The option values. */ public function all() { $this->reading = true; // Performance-wise this is slightly better than // while (null !== $option = key($this->lazy)) foreach ($this->lazy as $option => $closures) { // Double check, in case the option has already been resolved // by cascade in the previous cycles if (isset($this->lazy[$option])) { $this->resolve($option); } } foreach ($this->normalizers as $option => $normalizer) { if (isset($this->normalizers[$option])) { $this->normalize($option); } } return $this->options; } /** * Equivalent to {@link has()}. * * @param string $option The option name. * * @return Boolean Whether the option exists. * * @see \ArrayAccess::offsetExists() */ public function offsetExists($option) { return $this->has($option); } /** * Equivalent to {@link get()}. * * @param string $option The option name. * * @return mixed The option value. * * @throws \OutOfBoundsException If the option does not exist. * @throws OptionDefinitionException If a cyclic dependency is detected * between two lazy options. * * @see \ArrayAccess::offsetGet() */ public function offsetGet($option) { return $this->get($option); } /** * Equivalent to {@link set()}. * * @param string $option The name of the option. * @param mixed $value The value of the option. May be a closure with a * signature as defined in DefaultOptions::add(). * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. * * @see \ArrayAccess::offsetSet() */ public function offsetSet($option, $value) { $this->set($option, $value); } /** * Equivalent to {@link remove()}. * * @param string $option The option name. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. * * @see \ArrayAccess::offsetUnset() */ public function offsetUnset($option) { $this->remove($option); } /** * {@inheritdoc} */ public function current() { return $this->get($this->key()); } /** * {@inheritdoc} */ public function next() { next($this->options); } /** * {@inheritdoc} */ public function key() { return key($this->options); } /** * {@inheritdoc} */ public function valid() { return null !== $this->key(); } /** * {@inheritdoc} */ public function rewind() { reset($this->options); } /** * {@inheritdoc} */ public function count() { return count($this->options); } /** * Evaluates the given lazy option. * * The evaluated value is written into the options array. The closure for * evaluating the option is discarded afterwards. * * @param string $option The option to evaluate. * * @throws OptionDefinitionException If the option has a cyclic dependency * on another option. */ private function resolve($option) { // The code duplication with normalize() exists for performance // reasons, in order to save a method call. // Remember that this method is potentially called a couple of thousand // times and needs to be as efficient as possible. if (isset($this->lock[$option])) { $conflicts = array(); foreach ($this->lock as $option => $locked) { if ($locked) { $conflicts[] = $option; } } throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', implode('", "', $conflicts))); } $this->lock[$option] = true; foreach ($this->lazy[$option] as $closure) { $this->options[$option] = $closure($this, $this->options[$option]); } unset($this->lock[$option]); // The option now isn't lazy anymore unset($this->lazy[$option]); } /** * Normalizes the given option. * * The evaluated value is written into the options array. * * @param string $option The option to normalizer. * * @throws OptionDefinitionException If the option has a cyclic dependency * on another option. */ private function normalize($option) { // The code duplication with resolve() exists for performance // reasons, in order to save a method call. // Remember that this method is potentially called a couple of thousand // times and needs to be as efficient as possible. if (isset($this->lock[$option])) { $conflicts = array(); foreach ($this->lock as $option => $locked) { if ($locked) { $conflicts[] = $option; } } throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', implode('", "', $conflicts))); } /** @var \Closure $normalizer */ $normalizer = $this->normalizers[$option]; $this->lock[$option] = true; $this->options[$option] = $normalizer($this, array_key_exists($option, $this->options) ? $this->options[$option] : null); unset($this->lock[$option]); // The option is now normalized unset($this->normalizers[$option]); } } PK]G,OptionsResolver/OptionsResolverInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver; /** * @author Bernhard Schussek */ interface OptionsResolverInterface { /** * Sets default option values. * * The options can either be values of any types or closures that * evaluate the option value lazily. These closures must have one * of the following signatures: * * * function (Options $options) * function (Options $options, $value) * * * The second parameter passed to the closure is the previously * set default value, in case you are overwriting an existing * default value. * * The closures should return the lazily created option value. * * @param array $defaultValues A list of option names as keys and default * values or closures as values. * * @return OptionsResolverInterface The resolver instance. */ public function setDefaults(array $defaultValues); /** * Replaces default option values. * * Old defaults are erased, which means that closures passed here cannot * access the previous default value. This may be useful to improve * performance if the previous default value is calculated by an expensive * closure. * * @param array $defaultValues A list of option names as keys and default * values or closures as values. * * @return OptionsResolverInterface The resolver instance. */ public function replaceDefaults(array $defaultValues); /** * Sets optional options. * * This method declares valid option names without setting default values for them. * If these options are not passed to {@link resolve()} and no default has been set * for them, they will be missing in the final options array. This can be helpful * if you want to determine whether an option has been set or not because otherwise * {@link resolve()} would trigger an exception for unknown options. * * @param array $optionNames A list of option names. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\OptionDefinitionException When trying to pass default values. */ public function setOptional(array $optionNames); /** * Sets required options. * * If these options are not passed to {@link resolve()} and no default has been set for * them, an exception will be thrown. * * @param array $optionNames A list of option names. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\OptionDefinitionException When trying to pass default values. */ public function setRequired(array $optionNames); /** * Sets allowed values for a list of options. * * @param array $allowedValues A list of option names as keys and arrays * with values acceptable for that option as * values. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\InvalidOptionsException If an option has not been defined * (see {@link isKnown()}) for which * an allowed value is set. */ public function setAllowedValues(array $allowedValues); /** * Adds allowed values for a list of options. * * The values are merged with the allowed values defined previously. * * @param array $allowedValues A list of option names as keys and arrays * with values acceptable for that option as * values. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\InvalidOptionsException If an option has not been defined * (see {@link isKnown()}) for which * an allowed value is set. */ public function addAllowedValues(array $allowedValues); /** * Sets allowed types for a list of options. * * @param array $allowedTypes A list of option names as keys and type * names passed as string or array as values. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\InvalidOptionsException If an option has not been defined for * which an allowed type is set. */ public function setAllowedTypes(array $allowedTypes); /** * Adds allowed types for a list of options. * * The types are merged with the allowed types defined previously. * * @param array $allowedTypes A list of option names as keys and type * names passed as string or array as values. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\InvalidOptionsException If an option has not been defined for * which an allowed type is set. */ public function addAllowedTypes(array $allowedTypes); /** * Sets normalizers that are applied on resolved options. * * The normalizers should be closures with the following signature: * * * function (Options $options, $value) * * * The second parameter passed to the closure is the value of * the option. * * The closure should return the normalized value. * * @param array $normalizers An array of closures. * * @return OptionsResolverInterface The resolver instance. */ public function setNormalizers(array $normalizers); /** * Returns whether an option is known. * * An option is known if it has been passed to either {@link setDefaults()}, * {@link setRequired()} or {@link setOptional()} before. * * @param string $option The name of the option. * * @return Boolean Whether the option is known. */ public function isKnown($option); /** * Returns whether an option is required. * * An option is required if it has been passed to {@link setRequired()}, * but not to {@link setDefaults()}. That is, the option has been declared * as required and no default value has been set. * * @param string $option The name of the option. * * @return Boolean Whether the option is required. */ public function isRequired($option); /** * Returns the combination of the default and the passed options. * * @param array $options The custom option values. * * @return array A list of options and their values. * * @throws Exception\InvalidOptionsException If any of the passed options has not * been defined or does not contain an * allowed value. * @throws Exception\MissingOptionsException If a required option is missing. * @throws Exception\OptionDefinitionException If a cyclic dependency is detected * between two lazy options. */ public function resolve(array $options = array()); } PK]}8%8%#OptionsResolver/OptionsResolver.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver; use Symfony\Component\OptionsResolver\Exception\OptionDefinitionException; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; use Symfony\Component\OptionsResolver\Exception\MissingOptionsException; /** * Helper for merging default and concrete option values. * * @author Bernhard Schussek * @author Tobias Schultze */ class OptionsResolver implements OptionsResolverInterface { /** * The default option values. * @var Options */ private $defaultOptions; /** * The options known by the resolver. * @var array */ private $knownOptions = array(); /** * The options without defaults that are required to be passed to resolve(). * @var array */ private $requiredOptions = array(); /** * A list of accepted values for each option. * @var array */ private $allowedValues = array(); /** * A list of accepted types for each option. * @var array */ private $allowedTypes = array(); /** * Creates a new instance. */ public function __construct() { $this->defaultOptions = new Options(); } /** * Clones the resolver. */ public function __clone() { $this->defaultOptions = clone $this->defaultOptions; } /** * {@inheritdoc} */ public function setDefaults(array $defaultValues) { foreach ($defaultValues as $option => $value) { $this->defaultOptions->overload($option, $value); $this->knownOptions[$option] = true; unset($this->requiredOptions[$option]); } return $this; } /** * {@inheritdoc} */ public function replaceDefaults(array $defaultValues) { foreach ($defaultValues as $option => $value) { $this->defaultOptions->set($option, $value); $this->knownOptions[$option] = true; unset($this->requiredOptions[$option]); } return $this; } /** * {@inheritdoc} */ public function setOptional(array $optionNames) { foreach ($optionNames as $key => $option) { if (!is_int($key)) { throw new OptionDefinitionException('You should not pass default values to setOptional()'); } $this->knownOptions[$option] = true; } return $this; } /** * {@inheritdoc} */ public function setRequired(array $optionNames) { foreach ($optionNames as $key => $option) { if (!is_int($key)) { throw new OptionDefinitionException('You should not pass default values to setRequired()'); } $this->knownOptions[$option] = true; // set as required if no default has been set already if (!isset($this->defaultOptions[$option])) { $this->requiredOptions[$option] = true; } } return $this; } /** * {@inheritdoc} */ public function setAllowedValues(array $allowedValues) { $this->validateOptionsExistence($allowedValues); $this->allowedValues = array_replace($this->allowedValues, $allowedValues); return $this; } /** * {@inheritdoc} */ public function addAllowedValues(array $allowedValues) { $this->validateOptionsExistence($allowedValues); $this->allowedValues = array_merge_recursive($this->allowedValues, $allowedValues); return $this; } /** * {@inheritdoc} */ public function setAllowedTypes(array $allowedTypes) { $this->validateOptionsExistence($allowedTypes); $this->allowedTypes = array_replace($this->allowedTypes, $allowedTypes); return $this; } /** * {@inheritdoc} */ public function addAllowedTypes(array $allowedTypes) { $this->validateOptionsExistence($allowedTypes); $this->allowedTypes = array_merge_recursive($this->allowedTypes, $allowedTypes); return $this; } /** * {@inheritdoc} */ public function setNormalizers(array $normalizers) { $this->validateOptionsExistence($normalizers); foreach ($normalizers as $option => $normalizer) { $this->defaultOptions->setNormalizer($option, $normalizer); } return $this; } /** * {@inheritdoc} */ public function isKnown($option) { return isset($this->knownOptions[$option]); } /** * {@inheritdoc} */ public function isRequired($option) { return isset($this->requiredOptions[$option]); } /** * {@inheritdoc} */ public function resolve(array $options = array()) { $this->validateOptionsExistence($options); $this->validateOptionsCompleteness($options); // Make sure this method can be called multiple times $combinedOptions = clone $this->defaultOptions; // Override options set by the user foreach ($options as $option => $value) { $combinedOptions->set($option, $value); } // Resolve options $resolvedOptions = $combinedOptions->all(); $this->validateOptionValues($resolvedOptions); $this->validateOptionTypes($resolvedOptions); return $resolvedOptions; } /** * Validates that the given option names exist and throws an exception * otherwise. * * @param array $options An list of option names as keys. * * @throws InvalidOptionsException If any of the options has not been defined. */ private function validateOptionsExistence(array $options) { $diff = array_diff_key($options, $this->knownOptions); if (count($diff) > 0) { ksort($this->knownOptions); ksort($diff); throw new InvalidOptionsException(sprintf( (count($diff) > 1 ? 'The options "%s" do not exist.' : 'The option "%s" does not exist.').' Known options are: "%s"', implode('", "', array_keys($diff)), implode('", "', array_keys($this->knownOptions)) )); } } /** * Validates that all required options are given and throws an exception * otherwise. * * @param array $options An list of option names as keys. * * @throws MissingOptionsException If a required option is missing. */ private function validateOptionsCompleteness(array $options) { $diff = array_diff_key($this->requiredOptions, $options); if (count($diff) > 0) { ksort($diff); throw new MissingOptionsException(sprintf( count($diff) > 1 ? 'The required options "%s" are missing.' : 'The required option "%s" is missing.', implode('", "', array_keys($diff)) )); } } /** * Validates that the given option values match the allowed values and * throws an exception otherwise. * * @param array $options A list of option values. * * @throws InvalidOptionsException If any of the values does not match the * allowed values of the option. */ private function validateOptionValues(array $options) { foreach ($this->allowedValues as $option => $allowedValues) { if (isset($options[$option]) && !in_array($options[$option], $allowedValues, true)) { throw new InvalidOptionsException(sprintf('The option "%s" has the value "%s", but is expected to be one of "%s"', $option, $options[$option], implode('", "', $allowedValues))); } } } /** * Validates that the given options match the allowed types and * throws an exception otherwise. * * @param array $options A list of options. * * @throws InvalidOptionsException If any of the types does not match the * allowed types of the option. */ private function validateOptionTypes(array $options) { foreach ($this->allowedTypes as $option => $allowedTypes) { if (!array_key_exists($option, $options)) { continue; } $value = $options[$option]; $allowedTypes = (array) $allowedTypes; foreach ($allowedTypes as $type) { $isFunction = 'is_'.$type; if (function_exists($isFunction) && $isFunction($value)) { continue 2; } elseif ($value instanceof $type) { continue 2; } } $printableValue = is_object($value) ? get_class($value) : (is_array($value) ? 'Array' : (string) $value); throw new InvalidOptionsException(sprintf( 'The option "%s" with value "%s" is expected to be of type "%s"', $option, $printableValue, implode('", "', $allowedTypes) )); } } } PK]E@^0OptionsResolver/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver\Exception; /** * Marker interface for the Options component. * * @author Bernhard Schussek */ interface ExceptionInterface { } PK]sZ5OptionsResolver/Exception/InvalidOptionsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver\Exception; /** * Exception thrown when an invalid option is passed. * * @author Bernhard Schussek */ class InvalidOptionsException extends \InvalidArgumentException implements ExceptionInterface { } PK]yPH7OptionsResolver/Exception/OptionDefinitionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver\Exception; /** * Thrown when an option definition is invalid. * * @author Bernhard Schussek */ class OptionDefinitionException extends \RuntimeException implements ExceptionInterface { } PK] p5OptionsResolver/Exception/MissingOptionsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver\Exception; /** * Exception thrown when a required option is missing. * * @author Bernhard Schussek */ class MissingOptionsException extends \InvalidArgumentException implements ExceptionInterface { } PK]]='YYOptionsResolver/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; use Symfony\Component\DependencyInjection\Definition; /** * Lazy proxy dumper capable of generating the instantiation logic PHP code for proxied services. * * @author Marco Pivetta */ interface DumperInterface { /** * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container. * * @param Definition $definition * * @return bool */ public function isProxyCandidate(Definition $definition); /** * Generates the code to be used to instantiate a proxy in the dumped factory code. * * @param Definition $definition * @param string $id service identifier * * @return string */ public function getProxyFactoryCode(Definition $definition, $id); /** * Generates the code for the lazy proxy. * * @param Definition $definition * * @return string */ public function getProxyCode(Definition $definition); } PK]ҳ6DependencyInjection/LazyProxy/PhpDumper/NullDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; use Symfony\Component\DependencyInjection\Definition; /** * Null dumper, negates any proxy code generation for any given service definition. * * @author Marco Pivetta */ class NullDumper implements DumperInterface { /** * {@inheritDoc} */ public function isProxyCandidate(Definition $definition) { return false; } /** * {@inheritDoc} */ public function getProxyFactoryCode(Definition $definition, $id) { return ''; } /** * {@inheritDoc} */ public function getProxyCode(Definition $definition) { return ''; } } PK]innFDependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; /** * {@inheritDoc} * * Noop proxy instantiator - simply produces the real service instead of a proxy instance. * * @author Marco Pivetta */ class RealServiceInstantiator implements InstantiatorInterface { /** * {@inheritDoc} */ public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator) { return call_user_func($realInstantiator); } } PK]JJDDependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; /** * Lazy proxy instantiator, capable of instantiating a proxy given a container, the * service definitions and a callback that produces the real service instance. * * @author Marco Pivetta */ interface InstantiatorInterface { /** * Instantiates a proxy object. * * @param ContainerInterface $container the container from which the service is being requested * @param Definition $definition the definition of the requested service * @param string $id identifier of the requested service * @param callable $realInstantiator zero-argument callback that is capable of producing the real * service instance * * @return object */ public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator); } PK]0DependencyInjection/TaggedContainerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * TaggedContainerInterface is the interface implemented when a container knows how to deals with tags. * * @author Fabien Potencier * * @api */ interface TaggedContainerInterface extends ContainerInterface { /** * Returns service ids for a given tag. * * @param string $name The tag name * * @return array An array of tags * * @api */ public function findTaggedServiceIds($name); } PK]EBEB!DependencyInjection/Container.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InactiveScopeException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; /** * Container is a dependency injection container. * * It gives access to object instances (services). * * Services and parameters are simple key/pair stores. * * Parameter and service keys are case insensitive. * * A service id can contain lowercased letters, digits, underscores, and dots. * Underscores are used to separate words, and dots to group services * under namespaces: * *
    *
  • request
  • *
  • mysql_session_storage
  • *
  • symfony.mysql_session_storage
  • *
* * A service can also be defined by creating a method named * getXXXService(), where XXX is the camelized version of the id: * *
    *
  • request -> getRequestService()
  • *
  • mysql_session_storage -> getMysqlSessionStorageService()
  • *
  • symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()
  • *
* * The container can have three possible behaviors when a service does not exist: * * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) * * NULL_ON_INVALID_REFERENCE: Returns null * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference * (for instance, ignore a setter if the service does not exist) * * @author Fabien Potencier * @author Johannes M. Schmitt * * @api */ class Container implements IntrospectableContainerInterface { /** * @var ParameterBagInterface */ protected $parameterBag; protected $services = array(); protected $methodMap = array(); protected $aliases = array(); protected $scopes = array(); protected $scopeChildren = array(); protected $scopedServices = array(); protected $scopeStacks = array(); protected $loading = array(); /** * Constructor. * * @param ParameterBagInterface $parameterBag A ParameterBagInterface instance * * @api */ public function __construct(ParameterBagInterface $parameterBag = null) { $this->parameterBag = $parameterBag ?: new ParameterBag(); $this->set('service_container', $this); } /** * Compiles the container. * * This method does two things: * * * Parameter values are resolved; * * The parameter bag is frozen. * * @api */ public function compile() { $this->parameterBag->resolve(); $this->parameterBag = new FrozenParameterBag($this->parameterBag->all()); } /** * Returns true if the container parameter bag are frozen. * * @return Boolean true if the container parameter bag are frozen, false otherwise * * @api */ public function isFrozen() { return $this->parameterBag instanceof FrozenParameterBag; } /** * Gets the service container parameter bag. * * @return ParameterBagInterface A ParameterBagInterface instance * * @api */ public function getParameterBag() { return $this->parameterBag; } /** * Gets a parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws InvalidArgumentException if the parameter is not defined * * @api */ public function getParameter($name) { return $this->parameterBag->get($name); } /** * Checks if a parameter exists. * * @param string $name The parameter name * * @return Boolean The presence of parameter in container * * @api */ public function hasParameter($name) { return $this->parameterBag->has($name); } /** * Sets a parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function setParameter($name, $value) { $this->parameterBag->set($name, $value); } /** * Sets a service. * * Setting a service to null resets the service: has() returns false and get() * behaves in the same way as if the service was never created. * * @param string $id The service identifier * @param object $service The service instance * @param string $scope The scope of the service * * @throws RuntimeException When trying to set a service in an inactive scope * @throws InvalidArgumentException When trying to set a service in the prototype scope * * @api */ public function set($id, $service, $scope = self::SCOPE_CONTAINER) { if (self::SCOPE_PROTOTYPE === $scope) { throw new InvalidArgumentException(sprintf('You cannot set service "%s" of scope "prototype".', $id)); } $id = strtolower($id); if (self::SCOPE_CONTAINER !== $scope) { if (!isset($this->scopedServices[$scope])) { throw new RuntimeException(sprintf('You cannot set service "%s" of inactive scope.', $id)); } $this->scopedServices[$scope][$id] = $service; } $this->services[$id] = $service; if (method_exists($this, $method = 'synchronize'.strtr($id, array('_' => '', '.' => '_', '\\' => '_')).'Service')) { $this->$method(); } if (self::SCOPE_CONTAINER !== $scope && null === $service) { unset($this->scopedServices[$scope][$id]); } if (null === $service) { unset($this->services[$id]); } } /** * Returns true if the given service is defined. * * @param string $id The service identifier * * @return Boolean true if the service is defined, false otherwise * * @api */ public function has($id) { $id = strtolower($id); return isset($this->services[$id]) || array_key_exists($id, $this->services) || isset($this->aliases[$id]) || method_exists($this, 'get'.strtr($id, array('_' => '', '.' => '_', '\\' => '_')).'Service') ; } /** * Gets a service. * * If a service is defined both through a set() method and * with a get{$id}Service() method, the former has always precedence. * * @param string $id The service identifier * @param integer $invalidBehavior The behavior when the service does not exist * * @return object The associated service * * @throws InvalidArgumentException if the service is not defined * @throws ServiceCircularReferenceException When a circular reference is detected * @throws ServiceNotFoundException When the service is not defined * * @see Reference * * @api */ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE) { // Attempt to retrieve the service by checking first aliases then // available services. Service IDs are case insensitive, however since // this method can be called thousands of times during a request, avoid // calling strtolower() unless necessary. foreach (array(false, true) as $strtolower) { if ($strtolower) { $id = strtolower($id); } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; } // Re-use shared service instance if it exists. if (isset($this->services[$id]) || array_key_exists($id, $this->services)) { return $this->services[$id]; } } if (isset($this->loading[$id])) { throw new ServiceCircularReferenceException($id, array_keys($this->loading)); } if (isset($this->methodMap[$id])) { $method = $this->methodMap[$id]; } elseif (method_exists($this, $method = 'get'.strtr($id, array('_' => '', '.' => '_', '\\' => '_')).'Service')) { // $method is set to the right value, proceed } else { if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { if (!$id) { throw new ServiceNotFoundException($id); } $alternatives = array(); foreach (array_keys($this->services) as $key) { $lev = levenshtein($id, $key); if ($lev <= strlen($id) / 3 || false !== strpos($key, $id)) { $alternatives[] = $key; } } throw new ServiceNotFoundException($id, null, null, $alternatives); } return null; } $this->loading[$id] = true; try { $service = $this->$method(); } catch (\Exception $e) { unset($this->loading[$id]); if (array_key_exists($id, $this->services)) { unset($this->services[$id]); } if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return null; } throw $e; } unset($this->loading[$id]); return $service; } /** * Returns true if the given service has actually been initialized * * @param string $id The service identifier * * @return Boolean true if service has already been initialized, false otherwise */ public function initialized($id) { $id = strtolower($id); return isset($this->services[$id]) || array_key_exists($id, $this->services); } /** * Gets all service ids. * * @return array An array of all defined service ids */ public function getServiceIds() { $ids = array(); $r = new \ReflectionClass($this); foreach ($r->getMethods() as $method) { if (preg_match('/^get(.+)Service$/', $method->name, $match)) { $ids[] = self::underscore($match[1]); } } return array_unique(array_merge($ids, array_keys($this->services))); } /** * This is called when you enter a scope * * @param string $name * * @throws RuntimeException When the parent scope is inactive * @throws InvalidArgumentException When the scope does not exist * * @api */ public function enterScope($name) { if (!isset($this->scopes[$name])) { throw new InvalidArgumentException(sprintf('The scope "%s" does not exist.', $name)); } if (self::SCOPE_CONTAINER !== $this->scopes[$name] && !isset($this->scopedServices[$this->scopes[$name]])) { throw new RuntimeException(sprintf('The parent scope "%s" must be active when entering this scope.', $this->scopes[$name])); } // check if a scope of this name is already active, if so we need to // remove all services of this scope, and those of any of its child // scopes from the global services map if (isset($this->scopedServices[$name])) { $services = array($this->services, $name => $this->scopedServices[$name]); unset($this->scopedServices[$name]); foreach ($this->scopeChildren[$name] as $child) { if (isset($this->scopedServices[$child])) { $services[$child] = $this->scopedServices[$child]; unset($this->scopedServices[$child]); } } // update global map $this->services = call_user_func_array('array_diff_key', $services); array_shift($services); // add stack entry for this scope so we can restore the removed services later if (!isset($this->scopeStacks[$name])) { $this->scopeStacks[$name] = new \SplStack(); } $this->scopeStacks[$name]->push($services); } $this->scopedServices[$name] = array(); } /** * This is called to leave the current scope, and move back to the parent * scope. * * @param string $name The name of the scope to leave * * @throws InvalidArgumentException if the scope is not active * * @api */ public function leaveScope($name) { if (!isset($this->scopedServices[$name])) { throw new InvalidArgumentException(sprintf('The scope "%s" is not active.', $name)); } // remove all services of this scope, or any of its child scopes from // the global service map $services = array($this->services, $this->scopedServices[$name]); unset($this->scopedServices[$name]); foreach ($this->scopeChildren[$name] as $child) { if (!isset($this->scopedServices[$child])) { continue; } $services[] = $this->scopedServices[$child]; unset($this->scopedServices[$child]); } $this->services = call_user_func_array('array_diff_key', $services); // check if we need to restore services of a previous scope of this type if (isset($this->scopeStacks[$name]) && count($this->scopeStacks[$name]) > 0) { $services = $this->scopeStacks[$name]->pop(); $this->scopedServices += $services; foreach ($services as $array) { foreach ($array as $id => $service) { $this->set($id, $service, $name); } } } } /** * Adds a scope to the container. * * @param ScopeInterface $scope * * @throws InvalidArgumentException * * @api */ public function addScope(ScopeInterface $scope) { $name = $scope->getName(); $parentScope = $scope->getParentName(); if (self::SCOPE_CONTAINER === $name || self::SCOPE_PROTOTYPE === $name) { throw new InvalidArgumentException(sprintf('The scope "%s" is reserved.', $name)); } if (isset($this->scopes[$name])) { throw new InvalidArgumentException(sprintf('A scope with name "%s" already exists.', $name)); } if (self::SCOPE_CONTAINER !== $parentScope && !isset($this->scopes[$parentScope])) { throw new InvalidArgumentException(sprintf('The parent scope "%s" does not exist, or is invalid.', $parentScope)); } $this->scopes[$name] = $parentScope; $this->scopeChildren[$name] = array(); // normalize the child relations while ($parentScope !== self::SCOPE_CONTAINER) { $this->scopeChildren[$parentScope][] = $name; $parentScope = $this->scopes[$parentScope]; } } /** * Returns whether this container has a certain scope * * @param string $name The name of the scope * * @return Boolean * * @api */ public function hasScope($name) { return isset($this->scopes[$name]); } /** * Returns whether this scope is currently active * * This does not actually check if the passed scope actually exists. * * @param string $name * * @return Boolean * * @api */ public function isScopeActive($name) { return isset($this->scopedServices[$name]); } /** * Camelizes a string. * * @param string $id A string to camelize * * @return string The camelized string */ public static function camelize($id) { return strtr(ucwords(strtr($id, array('_' => ' ', '.' => '_ ', '\\' => '_ '))), array(' ' => '')); } /** * A string to underscore. * * @param string $id The string to underscore * * @return string The underscored string */ public static function underscore($id) { return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($id, '_', '.'))); } } PK]CoMM;DependencyInjection/Extension/PrependExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\ContainerBuilder; interface PrependExtensionInterface { /** * Allow an extension to prepend the extension configurations. * * @param ContainerBuilder $container */ public function prepend(ContainerBuilder $container); } PK]o +DependencyInjection/Extension/Extension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\Config\Definition\ConfigurationInterface; /** * Provides useful features shared by many extensions. * * @author Fabien Potencier */ abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface { /** * Returns the base path for the XSD files. * * @return string The XSD base path */ public function getXsdValidationBasePath() { return false; } /** * Returns the namespace to be used for this extension (XML namespace). * * @return string The XML namespace */ public function getNamespace() { return 'http://example.org/schema/dic/'.$this->getAlias(); } /** * Returns the recommended alias to use in XML. * * This alias is also the mandatory prefix to use when using YAML. * * This convention is to remove the "Extension" postfix from the class * name and then lowercase and underscore the result. So: * * AcmeHelloExtension * * becomes * * acme_hello * * This can be overridden in a sub-class to specify the alias manually. * * @return string The alias * * @throws BadMethodCallException When the extension name does not follow conventions */ public function getAlias() { $className = get_class($this); if (substr($className, -9) != 'Extension') { throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.'); } $classBaseName = substr(strrchr($className, '\\'), 1, -9); return Container::underscore($classBaseName); } /** * {@inheritDoc} */ public function getConfiguration(array $config, ContainerBuilder $container) { $reflected = new \ReflectionClass($this); $namespace = $reflected->getNamespaceName(); $class = $namespace.'\\Configuration'; if (class_exists($class)) { $r = new \ReflectionClass($class); $container->addResource(new FileResource($r->getFileName())); if (!method_exists($class, '__construct')) { $configuration = new $class(); return $configuration; } } return null; } final protected function processConfiguration(ConfigurationInterface $configuration, array $configs) { $processor = new Processor(); return $processor->processConfiguration($configuration, $configs); } /** * @param ContainerBuilder $container * @param array $config * * @return Boolean Whether the configuration is enabled * * @throws InvalidArgumentException When the config is not enableable */ protected function isConfigEnabled(ContainerBuilder $container, array $config) { if (!array_key_exists('enabled', $config)) { throw new InvalidArgumentException("The config array has no 'enabled' key."); } return (Boolean) $container->getParameterBag()->resolveValue($config['enabled']); } } PK]DS4DependencyInjection/Extension/ExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * ExtensionInterface is the interface implemented by container extension classes. * * @author Fabien Potencier * * @api */ interface ExtensionInterface { /** * Loads a specific configuration. * * @param array $config An array of configuration values * @param ContainerBuilder $container A ContainerBuilder instance * * @throws \InvalidArgumentException When provided tag is not defined in this extension * * @api */ public function load(array $config, ContainerBuilder $container); /** * Returns the namespace to be used for this extension (XML namespace). * * @return string The XML namespace * * @api */ public function getNamespace(); /** * Returns the base path for the XSD files. * * @return string The XSD base path * * @api */ public function getXsdValidationBasePath(); /** * Returns the recommended alias to use in XML. * * This alias is also the mandatory prefix to use when using YAML. * * @return string The alias * * @api */ public function getAlias(); } PK]JADependencyInjection/Extension/ConfigurationExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; /** * ConfigurationExtensionInterface is the interface implemented by container extension classes. * * @author Kevin Bond */ interface ConfigurationExtensionInterface { /** * Returns extension configuration * * @param array $config $config An array of configuration values * @param ContainerBuilder $container A ContainerBuilder instance * * @return ConfigurationInterface|null The configuration or null */ public function getConfiguration(array $config, ContainerBuilder $container); } PK];Yޯ*DependencyInjection/ExpressionLanguage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; /** * Adds some function to the default ExpressionLanguage. * * To get a service, use service('request'). * To get a parameter, use parameter('kernel.debug'). * * @author Fabien Potencier */ class ExpressionLanguage extends BaseExpressionLanguage { protected function registerFunctions() { parent::registerFunctions(); $this->register('service', function ($arg) { return sprintf('$this->get(%s)', $arg); }, function (array $variables, $value) { return $variables['container']->get($value); }); $this->register('parameter', function ($arg) { return sprintf('$this->getParameter(%s)', $arg); }, function (array $variables, $value) { return $variables['container']->getParameter($value); }); } } PK]l5DependencyInjection/Alias.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * @api */ class Alias { private $id; private $public; /** * Constructor. * * @param string $id Alias identifier * @param Boolean $public If this alias is public * * @api */ public function __construct($id, $public = true) { $this->id = strtolower($id); $this->public = $public; } /** * Checks if this DI Alias should be public or not. * * @return Boolean * * @api */ public function isPublic() { return $this->public; } /** * Sets if this Alias is public. * * @param Boolean $boolean If this Alias should be public * * @api */ public function setPublic($boolean) { $this->public = (Boolean) $boolean; } /** * Returns the Id of this alias. * * @return string The alias id * * @api */ public function __toString() { return $this->id; } } PK]**(DependencyInjection/Dumper/XmlDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\ExpressionLanguage\Expression; /** * XmlDumper dumps a service container as an XML string. * * @author Fabien Potencier * @author Martin Hasoň * * @api */ class XmlDumper extends Dumper { /** * @var \DOMDocument */ private $document; /** * Dumps the service container as an XML string. * * @param array $options An array of options * * @return string An xml string representing of the service container * * @api */ public function dump(array $options = array()) { $this->document = new \DOMDocument('1.0', 'utf-8'); $this->document->formatOutput = true; $container = $this->document->createElementNS('http://symfony.com/schema/dic/services', 'container'); $container->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd'); $this->addParameters($container); $this->addServices($container); $this->document->appendChild($container); $xml = $this->document->saveXML(); $this->document = null; return $xml; } /** * Adds parameters. * * @param \DOMElement $parent */ private function addParameters(\DOMElement $parent) { $data = $this->container->getParameterBag()->all(); if (!$data) { return; } if ($this->container->isFrozen()) { $data = $this->escape($data); } $parameters = $this->document->createElement('parameters'); $parent->appendChild($parameters); $this->convertParameters($data, 'parameter', $parameters); } /** * Adds method calls. * * @param array $methodcalls * @param \DOMElement $parent */ private function addMethodCalls(array $methodcalls, \DOMElement $parent) { foreach ($methodcalls as $methodcall) { $call = $this->document->createElement('call'); $call->setAttribute('method', $methodcall[0]); if (count($methodcall[1])) { $this->convertParameters($methodcall[1], 'argument', $call); } $parent->appendChild($call); } } /** * Adds a service. * * @param Definition $definition * @param string $id * @param \DOMElement $parent */ private function addService($definition, $id, \DOMElement $parent) { $service = $this->document->createElement('service'); if (null !== $id) { $service->setAttribute('id', $id); } if ($definition->getClass()) { $service->setAttribute('class', $definition->getClass()); } if ($definition->getFactoryMethod()) { $service->setAttribute('factory-method', $definition->getFactoryMethod()); } if ($definition->getFactoryService()) { $service->setAttribute('factory-service', $definition->getFactoryService()); } if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope()) { $service->setAttribute('scope', $scope); } if (!$definition->isPublic()) { $service->setAttribute('public', 'false'); } if ($definition->isSynthetic()) { $service->setAttribute('synthetic', 'true'); } if ($definition->isSynchronized()) { $service->setAttribute('synchronized', 'true'); } if ($definition->isLazy()) { $service->setAttribute('lazy', 'true'); } foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $tag = $this->document->createElement('tag'); $tag->setAttribute('name', $name); foreach ($attributes as $key => $value) { $tag->setAttribute($key, $value); } $service->appendChild($tag); } } if ($definition->getFile()) { $file = $this->document->createElement('file'); $file->appendChild($this->document->createTextNode($definition->getFile())); $service->appendChild($file); } if ($parameters = $definition->getArguments()) { $this->convertParameters($parameters, 'argument', $service); } if ($parameters = $definition->getProperties()) { $this->convertParameters($parameters, 'property', $service, 'name'); } $this->addMethodCalls($definition->getMethodCalls(), $service); if ($callable = $definition->getConfigurator()) { $configurator = $this->document->createElement('configurator'); if (is_array($callable)) { $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); $configurator->setAttribute('method', $callable[1]); } else { $configurator->setAttribute('function', $callable); } $service->appendChild($configurator); } $parent->appendChild($service); } /** * Adds a service alias. * * @param string $alias * @param Alias $id * @param \DOMElement $parent */ private function addServiceAlias($alias, Alias $id, \DOMElement $parent) { $service = $this->document->createElement('service'); $service->setAttribute('id', $alias); $service->setAttribute('alias', $id); if (!$id->isPublic()) { $service->setAttribute('public', 'false'); } $parent->appendChild($service); } /** * Adds services. * * @param \DOMElement $parent */ private function addServices(\DOMElement $parent) { $definitions = $this->container->getDefinitions(); if (!$definitions) { return; } $services = $this->document->createElement('services'); foreach ($definitions as $id => $definition) { $this->addService($definition, $id, $services); } $aliases = $this->container->getAliases(); foreach ($aliases as $alias => $id) { while (isset($aliases[(string) $id])) { $id = $aliases[(string) $id]; } $this->addServiceAlias($alias, $id, $services); } $parent->appendChild($services); } /** * Converts parameters. * * @param array $parameters * @param string $type * @param \DOMElement $parent * @param string $keyAttribute */ private function convertParameters($parameters, $type, \DOMElement $parent, $keyAttribute = 'key') { $withKeys = array_keys($parameters) !== range(0, count($parameters) - 1); foreach ($parameters as $key => $value) { $element = $this->document->createElement($type); if ($withKeys) { $element->setAttribute($keyAttribute, $key); } if (is_array($value)) { $element->setAttribute('type', 'collection'); $this->convertParameters($value, $type, $element, 'key'); } elseif ($value instanceof Reference) { $element->setAttribute('type', 'service'); $element->setAttribute('id', (string) $value); $behaviour = $value->getInvalidBehavior(); if ($behaviour == ContainerInterface::NULL_ON_INVALID_REFERENCE) { $element->setAttribute('on-invalid', 'null'); } elseif ($behaviour == ContainerInterface::IGNORE_ON_INVALID_REFERENCE) { $element->setAttribute('on-invalid', 'ignore'); } if (!$value->isStrict()) { $element->setAttribute('strict', 'false'); } } elseif ($value instanceof Definition) { $element->setAttribute('type', 'service'); $this->addService($value, null, $element); } elseif ($value instanceof Expression) { $element->setAttribute('type', 'expression'); $text = $this->document->createTextNode(self::phpToXml((string) $value)); $element->appendChild($text); } else { if (in_array($value, array('null', 'true', 'false'), true)) { $element->setAttribute('type', 'string'); } $text = $this->document->createTextNode(self::phpToXml($value)); $element->appendChild($text); } $parent->appendChild($element); } } /** * Escapes arguments * * @param array $arguments * * @return array */ private function escape($arguments) { $args = array(); foreach ($arguments as $k => $v) { if (is_array($v)) { $args[$k] = $this->escape($v); } elseif (is_string($v)) { $args[$k] = str_replace('%', '%%', $v); } else { $args[$k] = $v; } } return $args; } /** * Converts php types to xml types. * * @param mixed $value Value to convert * * @return string * * @throws RuntimeException When trying to dump object or resource */ public static function phpToXml($value) { switch (true) { case null === $value: return 'null'; case true === $value: return 'true'; case false === $value: return 'false'; case $value instanceof Parameter: return '%'.$value.'%'; case is_object($value) || is_resource($value): throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); default: return (string) $value; } } } PK]"^ (DependencyInjection/Dumper/PhpDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\Variable; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; use Symfony\Component\DependencyInjection\ExpressionLanguage; use Symfony\Component\ExpressionLanguage\Expression; /** * PhpDumper dumps a service container as a PHP class. * * @author Fabien Potencier * @author Johannes M. Schmitt * * @api */ class PhpDumper extends Dumper { /** * Characters that might appear in the generated variable name as first character * @var string */ const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz'; /** * Characters that might appear in the generated variable name as any but the first character * @var string */ const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_'; private $inlinedDefinitions; private $definitionVariables; private $referenceVariables; private $variableCount; private $reservedVariables = array('instance', 'class'); private $expressionLanguage; /** * @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface */ private $proxyDumper; /** * {@inheritDoc} * * @api */ public function __construct(ContainerBuilder $container) { parent::__construct($container); $this->inlinedDefinitions = new \SplObjectStorage(); } /** * Sets the dumper to be used when dumping proxies in the generated container. * * @param ProxyDumper $proxyDumper */ public function setProxyDumper(ProxyDumper $proxyDumper) { $this->proxyDumper = $proxyDumper; } /** * Dumps the service container as a PHP class. * * Available options: * * * class: The class name * * base_class: The base class name * * namespace: The class namespace * * @param array $options An array of options * * @return string A PHP class representing of the service container * * @api */ public function dump(array $options = array()) { $options = array_merge(array( 'class' => 'ProjectServiceContainer', 'base_class' => 'Container', 'namespace' => '', ), $options); $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']); if ($this->container->isFrozen()) { $code .= $this->addFrozenConstructor(); } else { $code .= $this->addConstructor(); } $code .= $this->addServices(). $this->addDefaultParametersMethod(). $this->endClass(). $this->addProxyClasses() ; return $code; } /** * Retrieves the currently set proxy dumper or instantiates one. * * @return ProxyDumper */ private function getProxyDumper() { if (!$this->proxyDumper) { $this->proxyDumper = new NullDumper(); } return $this->proxyDumper; } /** * Generates Service local temp variables. * * @param string $cId * @param string $definition * * @return string */ private function addServiceLocalTempVariables($cId, $definition) { static $template = " \$%s = %s;\n"; $localDefinitions = array_merge( array($definition), $this->getInlinedDefinitions($definition) ); $calls = $behavior = array(); foreach ($localDefinitions as $iDefinition) { $this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior); $this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior); $this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior); } $code = ''; foreach ($calls as $id => $callCount) { if ('service_container' === $id || $id === $cId) { continue; } if ($callCount > 1) { $name = $this->getNextVariableName(); $this->referenceVariables[$id] = new Variable($name); if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id]) { $code .= sprintf($template, $name, $this->getServiceCall($id)); } else { $code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, ContainerInterface::NULL_ON_INVALID_REFERENCE))); } } } if ('' !== $code) { $code .= "\n"; } return $code; } /** * Generates code for the proxies to be attached after the container class * * @return string */ private function addProxyClasses() { /* @var $definitions Definition[] */ $definitions = array_filter( $this->container->getDefinitions(), array($this->getProxyDumper(), 'isProxyCandidate') ); $code = ''; foreach ($definitions as $definition) { $code .= "\n" . $this->getProxyDumper()->getProxyCode($definition); } return $code; } /** * Generates the require_once statement for service includes. * * @param string $id The service id * @param Definition $definition * * @return string */ private function addServiceInclude($id, $definition) { $template = " require_once %s;\n"; $code = ''; if (null !== $file = $definition->getFile()) { $code .= sprintf($template, $this->dumpValue($file)); } foreach ($this->getInlinedDefinitions($definition) as $definition) { if (null !== $file = $definition->getFile()) { $code .= sprintf($template, $this->dumpValue($file)); } } if ('' !== $code) { $code .= "\n"; } return $code; } /** * Generates the inline definition of a service. * * @param string $id * @param Definition $definition * * @return string * * @throws RuntimeException When the factory definition is incomplete * @throws ServiceCircularReferenceException When a circular reference is detected */ private function addServiceInlinedDefinitions($id, $definition) { $code = ''; $variableMap = $this->definitionVariables; $nbOccurrences = new \SplObjectStorage(); $processed = new \SplObjectStorage(); $inlinedDefinitions = $this->getInlinedDefinitions($definition); foreach ($inlinedDefinitions as $definition) { if (false === $nbOccurrences->contains($definition)) { $nbOccurrences->offsetSet($definition, 1); } else { $i = $nbOccurrences->offsetGet($definition); $nbOccurrences->offsetSet($definition, $i + 1); } } foreach ($inlinedDefinitions as $sDefinition) { if ($processed->contains($sDefinition)) { continue; } $processed->offsetSet($sDefinition); $class = $this->dumpValue($sDefinition->getClass()); if ($nbOccurrences->offsetGet($sDefinition) > 1 || $sDefinition->getMethodCalls() || $sDefinition->getProperties() || null !== $sDefinition->getConfigurator() || false !== strpos($class, '$')) { $name = $this->getNextVariableName(); $variableMap->offsetSet($sDefinition, new Variable($name)); // a construct like: // $a = new ServiceA(ServiceB $b); $b = new ServiceB(ServiceA $a); // this is an indication for a wrong implementation, you can circumvent this problem // by setting up your service structure like this: // $b = new ServiceB(); // $a = new ServiceA(ServiceB $b); // $b->setServiceA(ServiceA $a); if ($this->hasReference($id, $sDefinition->getArguments())) { throw new ServiceCircularReferenceException($id, array($id)); } $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = '); if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) { $code .= $this->addServiceMethodCalls(null, $sDefinition, $name); $code .= $this->addServiceProperties(null, $sDefinition, $name); $code .= $this->addServiceConfigurator(null, $sDefinition, $name); } $code .= "\n"; } } return $code; } /** * Adds the service return statement. * * @param string $id Service id * @param Definition $definition * * @return string */ private function addServiceReturn($id, $definition) { if ($this->isSimpleInstance($id, $definition)) { return " }\n"; } return "\n return \$instance;\n }\n"; } /** * Generates the service instance. * * @param string $id * @param Definition $definition * * @return string * * @throws InvalidArgumentException * @throws RuntimeException */ private function addServiceInstance($id, $definition) { $class = $this->dumpValue($definition->getClass()); if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id)); } $simple = $this->isSimpleInstance($id, $definition); $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); $instantiation = ''; if (!$isProxyCandidate && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { $instantiation = "\$this->services['$id'] = ".($simple ? '' : '$instance'); } elseif (!$isProxyCandidate && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { $instantiation = "\$this->services['$id'] = \$this->scopedServices['$scope']['$id'] = ".($simple ? '' : '$instance'); } elseif (!$simple) { $instantiation = '$instance'; } $return = ''; if ($simple) { $return = 'return '; } else { $instantiation .= ' = '; } $code = $this->addNewInstance($id, $definition, $return, $instantiation); if (!$simple) { $code .= "\n"; } return $code; } /** * Checks if the definition is a simple instance. * * @param string $id * @param Definition $definition * * @return Boolean */ private function isSimpleInstance($id, $definition) { foreach (array_merge(array($definition), $this->getInlinedDefinitions($definition)) as $sDefinition) { if ($definition !== $sDefinition && !$this->hasReference($id, $sDefinition->getMethodCalls())) { continue; } if ($sDefinition->getMethodCalls() || $sDefinition->getProperties() || $sDefinition->getConfigurator()) { return false; } } return true; } /** * Adds method calls to a service definition. * * @param string $id * @param Definition $definition * @param string $variableName * * @return string */ private function addServiceMethodCalls($id, $definition, $variableName = 'instance') { $calls = ''; foreach ($definition->getMethodCalls() as $call) { $arguments = array(); foreach ($call[1] as $value) { $arguments[] = $this->dumpValue($value); } $calls .= $this->wrapServiceConditionals($call[1], sprintf(" \$%s->%s(%s);\n", $variableName, $call[0], implode(', ', $arguments))); } return $calls; } private function addServiceProperties($id, $definition, $variableName = 'instance') { $code = ''; foreach ($definition->getProperties() as $name => $value) { $code .= sprintf(" \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value)); } return $code; } /** * Generates the inline definition setup. * * @param string $id * @param Definition $definition * @return string */ private function addServiceInlinedDefinitionsSetup($id, $definition) { $this->referenceVariables[$id] = new Variable('instance'); $code = ''; $processed = new \SplObjectStorage(); foreach ($this->getInlinedDefinitions($definition) as $iDefinition) { if ($processed->contains($iDefinition)) { continue; } $processed->offsetSet($iDefinition); if (!$this->hasReference($id, $iDefinition->getMethodCalls(), true) && !$this->hasReference($id, $iDefinition->getProperties(), true)) { continue; } // if the instance is simple, the return statement has already been generated // so, the only possible way to get there is because of a circular reference if ($this->isSimpleInstance($id, $definition)) { throw new ServiceCircularReferenceException($id, array($id)); } $name = (string) $this->definitionVariables->offsetGet($iDefinition); $code .= $this->addServiceMethodCalls(null, $iDefinition, $name); $code .= $this->addServiceProperties(null, $iDefinition, $name); $code .= $this->addServiceConfigurator(null, $iDefinition, $name); } if ('' !== $code) { $code .= "\n"; } return $code; } /** * Adds configurator definition * * @param string $id * @param Definition $definition * @param string $variableName * * @return string */ private function addServiceConfigurator($id, $definition, $variableName = 'instance') { if (!$callable = $definition->getConfigurator()) { return ''; } if (is_array($callable)) { if ($callable[0] instanceof Reference) { return sprintf(" %s->%s(\$%s);\n", $this->getServiceCall((string) $callable[0]), $callable[1], $variableName); } return sprintf(" call_user_func(array(%s, '%s'), \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); } return sprintf(" %s(\$%s);\n", $callable, $variableName); } /** * Adds a service * * @param string $id * @param Definition $definition * * @return string */ private function addService($id, $definition) { $this->definitionVariables = new \SplObjectStorage(); $this->referenceVariables = array(); $this->variableCount = 0; $return = array(); if ($definition->isSynthetic()) { $return[] = '@throws RuntimeException always since this service is expected to be injected dynamically'; } elseif ($class = $definition->getClass()) { $return[] = sprintf("@return %s A %s instance.", 0 === strpos($class, '%') ? 'object' : $class, $class); } elseif ($definition->getFactoryClass()) { $return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryClass(), $definition->getFactoryMethod()); } elseif ($definition->getFactoryService()) { $return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryService(), $definition->getFactoryMethod()); } $scope = $definition->getScope(); if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) { if ($return && 0 === strpos($return[count($return) - 1], '@return')) { $return[] = ''; } $return[] = sprintf("@throws InactiveScopeException when the '%s' service is requested while the '%s' scope is not active", $id, $scope); } $return = implode("\n * ", $return); $doc = ''; if (ContainerInterface::SCOPE_PROTOTYPE !== $scope) { $doc .= <<isPublic()) { $doc .= <<isLazy()) { $lazyInitialization = '$lazyLoad = true'; $lazyInitializationDoc = "\n * @param boolean \$lazyLoad whether to try lazy-loading the service with a proxy\n *"; } else { $lazyInitialization = ''; $lazyInitializationDoc = ''; } // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); $visibility = $isProxyCandidate ? 'public' : 'protected'; $code = <<camelize($id)}Service($lazyInitialization) { EOF; $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id) : ''; if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) { $code .= <<scopedServices['$scope'])) { throw new InactiveScopeException('$id', '$scope'); } EOF; } if ($definition->isSynthetic()) { $code .= sprintf(" throw new RuntimeException('You have requested a synthetic service (\"%s\"). The DIC does not know how to construct this service.');\n }\n", $id); } else { $code .= $this->addServiceInclude($id, $definition). $this->addServiceLocalTempVariables($id, $definition). $this->addServiceInlinedDefinitions($id, $definition). $this->addServiceInstance($id, $definition). $this->addServiceInlinedDefinitionsSetup($id, $definition). $this->addServiceMethodCalls($id, $definition). $this->addServiceProperties($id, $definition). $this->addServiceConfigurator($id, $definition). $this->addServiceReturn($id, $definition) ; } $this->definitionVariables = null; $this->referenceVariables = null; return $code; } /** * Adds multiple services * * @return string */ private function addServices() { $publicServices = $privateServices = $synchronizers = ''; $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { if ($definition->isPublic()) { $publicServices .= $this->addService($id, $definition); } else { $privateServices .= $this->addService($id, $definition); } $synchronizers .= $this->addServiceSynchronizer($id, $definition); } return $publicServices.$synchronizers.$privateServices; } /** * Adds synchronizer methods. * * @param string $id A service identifier * @param Definition $definition A Definition instance */ private function addServiceSynchronizer($id, Definition $definition) { if (!$definition->isSynchronized()) { return; } $code = ''; foreach ($this->container->getDefinitions() as $definitionId => $definition) { foreach ($definition->getMethodCalls() as $call) { foreach ($call[1] as $argument) { if ($argument instanceof Reference && $id == (string) $argument) { $arguments = array(); foreach ($call[1] as $value) { $arguments[] = $this->dumpValue($value); } $call = $this->wrapServiceConditionals($call[1], sprintf("\$this->get('%s')->%s(%s);", $definitionId, $call[0], implode(', ', $arguments))); $code .= <<initialized('$definitionId')) { $call } EOF; } } } } if (!$code) { return; } return <<camelize($id)}Service() { $code } EOF; } private function addNewInstance($id, Definition $definition, $return, $instantiation) { $class = $this->dumpValue($definition->getClass()); $arguments = array(); foreach ($definition->getArguments() as $value) { $arguments[] = $this->dumpValue($value); } if (null !== $definition->getFactoryMethod()) { if (null !== $definition->getFactoryClass()) { return sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass()), $definition->getFactoryMethod(), $arguments ? ', '.implode(', ', $arguments) : ''); } if (null !== $definition->getFactoryService()) { return sprintf(" $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments)); } throw new RuntimeException(sprintf('Factory method requires a factory service or factory class in service definition for %s', $id)); } if (false !== strpos($class, '$')) { return sprintf(" \$class = %s;\n\n $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments)); } return sprintf(" $return{$instantiation}new \\%s(%s);\n", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments)); } /** * Adds the class headers. * * @param string $class Class name * @param string $baseClass The name of the base class * @param string $namespace The class namespace * * @return string */ private function startClass($class, $baseClass, $namespace) { $bagClass = $this->container->isFrozen() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;'; $namespaceLine = $namespace ? "namespace $namespace;\n" : ''; return <<container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null; $code = <<container->getScopes()) > 0) { $code .= "\n"; $code .= " \$this->scopes = ".$this->dumpValue($scopes).";\n"; $code .= " \$this->scopeChildren = ".$this->dumpValue($this->container->getScopeChildren()).";\n"; } $code .= $this->addMethodMap(); $code .= $this->addAliases(); $code .= <<container->getParameterBag()->all()) { $code .= "\n \$this->parameters = \$this->getDefaultParameters();\n"; } $code .= <<services = \$this->scopedServices = \$this->scopeStacks = array(); \$this->set('service_container', \$this); EOF; $code .= "\n"; if (count($scopes = $this->container->getScopes()) > 0) { $code .= " \$this->scopes = ".$this->dumpValue($scopes).";\n"; $code .= " \$this->scopeChildren = ".$this->dumpValue($this->container->getScopeChildren()).";\n"; } else { $code .= " \$this->scopes = array();\n"; $code .= " \$this->scopeChildren = array();\n"; } $code .= $this->addMethodMap(); $code .= $this->addAliases(); $code .= <<container->getDefinitions()) { return ''; } $code = " \$this->methodMap = array(\n"; ksort($definitions); foreach ($definitions as $id => $definition) { $code .= ' '.var_export($id, true).' => '.var_export('get'.$this->camelize($id).'Service', true).",\n"; } return $code . " );\n"; } /** * Adds the aliases property definition * * @return string */ private function addAliases() { if (!$aliases = $this->container->getAliases()) { if ($this->container->isFrozen()) { return "\n \$this->aliases = array();\n"; } else { return ''; } } $code = " \$this->aliases = array(\n"; ksort($aliases); foreach ($aliases as $alias => $id) { $id = (string) $id; while (isset($aliases[$id])) { $id = (string) $aliases[$id]; } $code .= ' '.var_export($alias, true).' => '.var_export($id, true).",\n"; } return $code . " );\n"; } /** * Adds default parameters method. * * @return string */ private function addDefaultParametersMethod() { if (!$this->container->getParameterBag()->all()) { return ''; } $parameters = $this->exportParameters($this->container->getParameterBag()->all()); $code = ''; if ($this->container->isFrozen()) { $code .= <<parameters[\$name]) || array_key_exists(\$name, \$this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', \$name)); } return \$this->parameters[\$name]; } /** * {@inheritdoc} */ public function hasParameter(\$name) { \$name = strtolower(\$name); return isset(\$this->parameters[\$name]) || array_key_exists(\$name, \$this->parameters); } /** * {@inheritdoc} */ public function setParameter(\$name, \$value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } /** * {@inheritDoc} */ public function getParameterBag() { if (null === \$this->parameterBag) { \$this->parameterBag = new FrozenParameterBag(\$this->parameters); } return \$this->parameterBag; } EOF; } $code .= << $value) { if (is_array($value)) { $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4); } elseif ($value instanceof Variable) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key)); } elseif ($value instanceof Definition) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain service definitions. Definition for "%s" found in "%s".', $value->getClass(), $path.'/'.$key)); } elseif ($value instanceof Reference) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain references to other services (reference to service "%s" found in "%s").', $value, $path.'/'.$key)); } elseif ($value instanceof Expression) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path.'/'.$key)); } else { $value = var_export($value, true); } $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), var_export($key, true), $value); } return sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', $indent - 4)); } /** * Ends the class definition. * * @return string */ private function endClass() { return <<has('%s')", $service); } // re-indent the wrapped code $code = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $code))); return sprintf(" if (%s) {\n%s }\n", implode(' && ', $conditions), $code); } /** * Builds service calls from arguments. * * @param array $arguments * @param array &$calls By reference * @param array &$behavior By reference */ private function getServiceCallsFromArguments(array $arguments, array &$calls, array &$behavior) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->getServiceCallsFromArguments($argument, $calls, $behavior); } elseif ($argument instanceof Reference) { $id = (string) $argument; if (!isset($calls[$id])) { $calls[$id] = 0; } if (!isset($behavior[$id])) { $behavior[$id] = $argument->getInvalidBehavior(); } elseif (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $behavior[$id]) { $behavior[$id] = $argument->getInvalidBehavior(); } $calls[$id] += 1; } } } /** * Returns the inline definition. * * @param Definition $definition * * @return array */ private function getInlinedDefinitions(Definition $definition) { if (false === $this->inlinedDefinitions->contains($definition)) { $definitions = array_merge( $this->getDefinitionsFromArguments($definition->getArguments()), $this->getDefinitionsFromArguments($definition->getMethodCalls()), $this->getDefinitionsFromArguments($definition->getProperties()) ); $this->inlinedDefinitions->offsetSet($definition, $definitions); return $definitions; } return $this->inlinedDefinitions->offsetGet($definition); } /** * Gets the definition from arguments. * * @param array $arguments * * @return array */ private function getDefinitionsFromArguments(array $arguments) { $definitions = array(); foreach ($arguments as $argument) { if (is_array($argument)) { $definitions = array_merge($definitions, $this->getDefinitionsFromArguments($argument)); } elseif ($argument instanceof Definition) { $definitions = array_merge( $definitions, $this->getInlinedDefinitions($argument), array($argument) ); } } return $definitions; } /** * Checks if a service id has a reference. * * @param string $id * @param array $arguments * @param Boolean $deep * @param array $visited * * @return Boolean */ private function hasReference($id, array $arguments, $deep = false, array $visited = array()) { foreach ($arguments as $argument) { if (is_array($argument)) { if ($this->hasReference($id, $argument, $deep, $visited)) { return true; } } elseif ($argument instanceof Reference) { $argumentId = (string) $argument; if ($id === $argumentId) { return true; } if ($deep && !isset($visited[$argumentId])) { $visited[$argumentId] = true; $service = $this->container->getDefinition($argumentId); $arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties()); if ($this->hasReference($id, $arguments, $deep, $visited)) { return true; } } } } return false; } /** * Dumps values. * * @param array $value * @param Boolean $interpolate * * @return string * * @throws RuntimeException */ private function dumpValue($value, $interpolate = true) { if (is_array($value)) { $code = array(); foreach ($value as $k => $v) { $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)); } return sprintf('array(%s)', implode(', ', $code)); } elseif ($value instanceof Definition) { if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) { return $this->dumpValue($this->definitionVariables->offsetGet($value), $interpolate); } if (count($value->getMethodCalls()) > 0) { throw new RuntimeException('Cannot dump definitions which have method calls.'); } if (null !== $value->getConfigurator()) { throw new RuntimeException('Cannot dump definitions which have a configurator.'); } $arguments = array(); foreach ($value->getArguments() as $argument) { $arguments[] = $this->dumpValue($argument); } $class = $this->dumpValue($value->getClass()); if (false !== strpos($class, '$')) { throw new RuntimeException('Cannot dump definitions which have a variable class name.'); } if (null !== $value->getFactoryMethod()) { if (null !== $value->getFactoryClass()) { return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($value->getFactoryClass()), $value->getFactoryMethod(), count($arguments) > 0 ? ', '.implode(', ', $arguments) : ''); } elseif (null !== $value->getFactoryService()) { return sprintf("%s->%s(%s)", $this->getServiceCall($value->getFactoryService()), $value->getFactoryMethod(), implode(', ', $arguments)); } else { throw new RuntimeException('Cannot dump definitions which have factory method without factory service or factory class.'); } } return sprintf("new \\%s(%s)", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments)); } elseif ($value instanceof Variable) { return '$'.$value; } elseif ($value instanceof Reference) { if (null !== $this->referenceVariables && isset($this->referenceVariables[$id = (string) $value])) { return $this->dumpValue($this->referenceVariables[$id], $interpolate); } return $this->getServiceCall((string) $value, $value); } elseif ($value instanceof Expression) { return $this->getExpressionLanguage()->compile((string) $value, array('container')); } elseif ($value instanceof Parameter) { return $this->dumpParameter($value); } elseif (true === $interpolate && is_string($value)) { if (preg_match('/^%([^%]+)%$/', $value, $match)) { // we do this to deal with non string values (Boolean, integer, ...) // the preg_replace_callback converts them to strings return $this->dumpParameter(strtolower($match[1])); } else { $that = $this; $replaceParameters = function ($match) use ($that) { return "'.".$that->dumpParameter(strtolower($match[2])).".'"; }; $code = str_replace('%%', '%', preg_replace_callback('/(?container->isFrozen() && $this->container->hasParameter($name)) { return $this->dumpValue($this->container->getParameter($name), false); } return sprintf("\$this->getParameter('%s')", strtolower($name)); } /** * Gets a service call * * @param string $id * @param Reference $reference * * @return string */ private function getServiceCall($id, Reference $reference = null) { if ('service_container' === $id) { return '$this'; } if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { return sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id); } else { if ($this->container->hasAlias($id)) { $id = (string) $this->container->getAlias($id); } return sprintf('$this->get(\'%s\')', $id); } } /** * Convert a service id to a valid PHP method name. * * @param string $id * * @return string * * @throws InvalidArgumentException */ private function camelize($id) { $name = Container::camelize($id); if (!preg_match('/^[a-zA-Z0-9_\x7f-\xff]+$/', $name)) { throw new InvalidArgumentException(sprintf('Service id "%s" cannot be converted to a valid PHP method name.', $id)); } return $name; } /** * Returns the next name to use * * @return string */ private function getNextVariableName() { $firstChars = self::FIRST_CHARS; $firstCharsLength = strlen($firstChars); $nonFirstChars = self::NON_FIRST_CHARS; $nonFirstCharsLength = strlen($nonFirstChars); while (true) { $name = ''; $i = $this->variableCount; if ('' === $name) { $name .= $firstChars[$i%$firstCharsLength]; $i = intval($i/$firstCharsLength); } while ($i > 0) { $i -= 1; $name .= $nonFirstChars[$i%$nonFirstCharsLength]; $i = intval($i/$nonFirstCharsLength); } $this->variableCount += 1; // check that the name is not reserved if (in_array($name, $this->reservedVariables, true)) { continue; } return $name; } } private function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(); } return $this->expressionLanguage; } } PK]}.DependencyInjection/Dumper/DumperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; /** * DumperInterface is the interface implemented by service container dumper classes. * * @author Fabien Potencier * * @api */ interface DumperInterface { /** * Dumps the service container. * * @param array $options An array of options * * @return string The representation of the service container * * @api */ public function dump(array $options = array()); } PK]N/++%DependencyInjection/Dumper/Dumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Dumper is the abstract class for all built-in dumpers. * * @author Fabien Potencier * * @api */ abstract class Dumper implements DumperInterface { protected $container; /** * Constructor. * * @param ContainerBuilder $container The service container to dump * * @api */ public function __construct(ContainerBuilder $container) { $this->container = $container; } } PK]%%-DependencyInjection/Dumper/GraphvizDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; /** * GraphvizDumper dumps a service container as a graphviz file. * * You can convert the generated dot file with the dot utility (http://www.graphviz.org/): * * dot -Tpng container.dot > foo.png * * @author Fabien Potencier */ class GraphvizDumper extends Dumper { private $nodes; private $edges; private $options = array( 'graph' => array('ratio' => 'compress'), 'node' => array('fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'), 'edge' => array('fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5), 'node.instance' => array('fillcolor' => '#9999ff', 'style' => 'filled'), 'node.definition' => array('fillcolor' => '#eeeeee'), 'node.missing' => array('fillcolor' => '#ff9999', 'style' => 'filled'), ); /** * Dumps the service container as a graphviz graph. * * Available options: * * * graph: The default options for the whole graph * * node: The default options for nodes * * edge: The default options for edges * * node.instance: The default options for services that are defined directly by object instances * * node.definition: The default options for services that are defined via service definition instances * * node.missing: The default options for missing services * * @param array $options An array of options * * @return string The dot representation of the service container */ public function dump(array $options = array()) { foreach (array('graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing') as $key) { if (isset($options[$key])) { $this->options[$key] = array_merge($this->options[$key], $options[$key]); } } $this->nodes = $this->findNodes(); $this->edges = array(); foreach ($this->container->getDefinitions() as $id => $definition) { $this->edges[$id] = array_merge( $this->findEdges($id, $definition->getArguments(), true, ''), $this->findEdges($id, $definition->getProperties(), false, '') ); foreach ($definition->getMethodCalls() as $call) { $this->edges[$id] = array_merge( $this->edges[$id], $this->findEdges($id, $call[1], false, $call[0].'()') ); } } return $this->startDot().$this->addNodes().$this->addEdges().$this->endDot(); } /** * Returns all nodes. * * @return string A string representation of all nodes */ private function addNodes() { $code = ''; foreach ($this->nodes as $id => $node) { $aliases = $this->getAliases($id); $code .= sprintf(" node_%s [label=\"%s\\n%s\\n\", shape=%s%s];\n", $this->dotize($id), $id.($aliases ? ' ('.implode(', ', $aliases).')' : ''), $node['class'], $this->options['node']['shape'], $this->addAttributes($node['attributes'])); } return $code; } /** * Returns all edges. * * @return string A string representation of all edges */ private function addEdges() { $code = ''; foreach ($this->edges as $id => $edges) { foreach ($edges as $edge) { $code .= sprintf(" node_%s -> node_%s [label=\"%s\" style=\"%s\"];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed'); } } return $code; } /** * Finds all edges belonging to a specific service id. * * @param string $id The service id used to find edges * @param array $arguments An array of arguments * @param Boolean $required * @param string $name * * @return array An array of edges */ private function findEdges($id, $arguments, $required, $name) { $edges = array(); foreach ($arguments as $argument) { if ($argument instanceof Parameter) { $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null; } elseif (is_string($argument) && preg_match('/^%([^%]+)%$/', $argument, $match)) { $argument = $this->container->hasParameter($match[1]) ? $this->container->getParameter($match[1]) : null; } if ($argument instanceof Reference) { if (!$this->container->has((string) $argument)) { $this->nodes[(string) $argument] = array('name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']); } $edges[] = array('name' => $name, 'required' => $required, 'to' => $argument); } elseif (is_array($argument)) { $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name)); } } return $edges; } /** * Finds all nodes. * * @return array An array of all nodes */ private function findNodes() { $nodes = array(); $container = $this->cloneContainer(); foreach ($container->getDefinitions() as $id => $definition) { $nodes[$id] = array('class' => str_replace('\\', '\\\\', $this->container->getParameterBag()->resolveValue($definition->getClass())), 'attributes' => array_merge($this->options['node.definition'], array('style' => ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope() ? 'filled' : 'dotted'))); $container->setDefinition($id, new Definition('stdClass')); } foreach ($container->getServiceIds() as $id) { $service = $container->get($id); if (in_array($id, array_keys($container->getAliases()))) { continue; } if (!$container->hasDefinition($id)) { $class = ('service_container' === $id) ? get_class($this->container) : get_class($service); $nodes[$id] = array('class' => str_replace('\\', '\\\\', $class), 'attributes' => $this->options['node.instance']); } } return $nodes; } private function cloneContainer() { $parameterBag = new ParameterBag($this->container->getParameterBag()->all()); $container = new ContainerBuilder($parameterBag); $container->setDefinitions($this->container->getDefinitions()); $container->setAliases($this->container->getAliases()); $container->setResources($this->container->getResources()); foreach ($this->container->getScopes() as $scope) { $container->addScope($scope); } foreach ($this->container->getExtensions() as $extension) { $container->registerExtension($extension); } return $container; } /** * Returns the start dot. * * @return string The string representation of a start dot */ private function startDot() { return sprintf("digraph sc {\n %s\n node [%s];\n edge [%s];\n\n", $this->addOptions($this->options['graph']), $this->addOptions($this->options['node']), $this->addOptions($this->options['edge']) ); } /** * Returns the end dot. * * @return string */ private function endDot() { return "}\n"; } /** * Adds attributes * * @param array $attributes An array of attributes * * @return string A comma separated list of attributes */ private function addAttributes($attributes) { $code = array(); foreach ($attributes as $k => $v) { $code[] = sprintf('%s="%s"', $k, $v); } return $code ? ', '.implode(', ', $code) : ''; } /** * Adds options * * @param array $options An array of options * * @return string A space separated list of options */ private function addOptions($options) { $code = array(); foreach ($options as $k => $v) { $code[] = sprintf('%s="%s"', $k, $v); } return implode(' ', $code); } /** * Dotizes an identifier. * * @param string $id The identifier to dotize * * @return string A dotized string */ private function dotize($id) { return strtolower(preg_replace('/[^\w]/i', '_', $id)); } /** * Compiles an array of aliases for a specified service id. * * @param string $id A service id * * @return array An array of aliases */ private function getAliases($id) { $aliases = array(); foreach ($this->container->getAliases() as $alias => $origin) { if ($id == $origin) { $aliases[] = $alias; } } return $aliases; } } PK]A:$:$)DependencyInjection/Dumper/YamlDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\Yaml\Dumper as YmlDumper; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\ExpressionLanguage\Expression; /** * YamlDumper dumps a service container as a YAML string. * * @author Fabien Potencier * * @api */ class YamlDumper extends Dumper { private $dumper; /** * Constructor. * * @param ContainerBuilder $container The service container to dump * * @api */ public function __construct(ContainerBuilder $container) { parent::__construct($container); $this->dumper = new YmlDumper(); } /** * Dumps the service container as an YAML string. * * @param array $options An array of options * * @return string A YAML string representing of the service container * * @api */ public function dump(array $options = array()) { return $this->addParameters()."\n".$this->addServices(); } /** * Adds a service * * @param string $id * @param Definition $definition * * @return string */ private function addService($id, $definition) { $code = " $id:\n"; if ($definition->getClass()) { $code .= sprintf(" class: %s\n", $definition->getClass()); } if (!$definition->isPublic()) { $code .= " public: false\n"; } $tagsCode = ''; foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $att = array(); foreach ($attributes as $key => $value) { $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value)); } $att = $att ? ', '.implode(' ', $att) : ''; $tagsCode .= sprintf(" - { name: %s%s }\n", $this->dumper->dump($name), $att); } } if ($tagsCode) { $code .= " tags:\n".$tagsCode; } if ($definition->getFile()) { $code .= sprintf(" file: %s\n", $definition->getFile()); } if ($definition->isSynthetic()) { $code .= sprintf(" synthetic: true\n"); } if ($definition->isSynchronized()) { $code .= sprintf(" synchronized: true\n"); } if ($definition->getFactoryClass()) { $code .= sprintf(" factory_class: %s\n", $definition->getFactoryClass()); } if ($definition->isLazy()) { $code .= sprintf(" lazy: true\n"); } if ($definition->getFactoryMethod()) { $code .= sprintf(" factory_method: %s\n", $definition->getFactoryMethod()); } if ($definition->getFactoryService()) { $code .= sprintf(" factory_service: %s\n", $definition->getFactoryService()); } if ($definition->getArguments()) { $code .= sprintf(" arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0)); } if ($definition->getProperties()) { $code .= sprintf(" properties: %s\n", $this->dumper->dump($this->dumpValue($definition->getProperties()), 0)); } if ($definition->getMethodCalls()) { $code .= sprintf(" calls:\n%s\n", $this->dumper->dump($this->dumpValue($definition->getMethodCalls()), 1, 12)); } if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope()) { $code .= sprintf(" scope: %s\n", $scope); } if ($callable = $definition->getConfigurator()) { if (is_array($callable)) { if ($callable[0] instanceof Reference) { $callable = array($this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]); } else { $callable = array($callable[0], $callable[1]); } } $code .= sprintf(" configurator: %s\n", $this->dumper->dump($callable, 0)); } return $code; } /** * Adds a service alias * * @param string $alias * @param Alias $id * * @return string */ private function addServiceAlias($alias, $id) { if ($id->isPublic()) { return sprintf(" %s: @%s\n", $alias, $id); } else { return sprintf(" %s:\n alias: %s\n public: false", $alias, $id); } } /** * Adds services * * @return string */ private function addServices() { if (!$this->container->getDefinitions()) { return ''; } $code = "services:\n"; foreach ($this->container->getDefinitions() as $id => $definition) { $code .= $this->addService($id, $definition); } $aliases = $this->container->getAliases(); foreach ($aliases as $alias => $id) { while (isset($aliases[(string) $id])) { $id = $aliases[(string) $id]; } $code .= $this->addServiceAlias($alias, $id); } return $code; } /** * Adds parameters * * @return string */ private function addParameters() { if (!$this->container->getParameterBag()->all()) { return ''; } $parameters = $this->prepareParameters($this->container->getParameterBag()->all(), $this->container->isFrozen()); return $this->dumper->dump(array('parameters' => $parameters), 2); } /** * Dumps the value to YAML format * * @param mixed $value * * @return mixed * * @throws RuntimeException When trying to dump object or resource */ private function dumpValue($value) { if (is_array($value)) { $code = array(); foreach ($value as $k => $v) { $code[$k] = $this->dumpValue($v); } return $code; } elseif ($value instanceof Reference) { return $this->getServiceCall((string) $value, $value); } elseif ($value instanceof Parameter) { return $this->getParameterCall((string) $value); } elseif ($value instanceof Expression) { return $this->getExpressionCall((string) $value); } elseif (is_object($value) || is_resource($value)) { throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); } return $value; } /** * Gets the service call. * * @param string $id * @param Reference $reference * * @return string */ private function getServiceCall($id, Reference $reference = null) { if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { return sprintf('@?%s', $id); } return sprintf('@%s', $id); } /** * Gets parameter call. * * @param string $id * * @return string */ private function getParameterCall($id) { return sprintf('%%%s%%', $id); } private function getExpressionCall($expression) { return sprintf('@=%s', $expression); } /** * Prepares parameters. * * @param array $parameters * @param Boolean $escape * * @return array */ private function prepareParameters($parameters, $escape = true) { $filtered = array(); foreach ($parameters as $key => $value) { if (is_array($value)) { $value = $this->prepareParameters($value, $escape); } elseif ($value instanceof Reference || is_string($value) && 0 === strpos($value, '@')) { $value = '@'.$value; } $filtered[$key] = $value; } return $escape ? $this->escape($filtered) : $filtered; } /** * Escapes arguments * * @param array $arguments * * @return array */ private function escape($arguments) { $args = array(); foreach ($arguments as $k => $v) { if (is_array($v)) { $args[$k] = $this->escape($v); } elseif (is_string($v)) { $args[$k] = str_replace('%', '%%', $v); } else { $args[$k] = $v; } } return $args; } } PK]$77 DependencyInjection/Variable.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Represents a variable. * * $var = new Variable('a'); * * will be dumped as * * $a * * by the PHP dumper. * * @author Johannes M. Schmitt */ class Variable { private $name; /** * Constructor * * @param string $name */ public function __construct($name) { $this->name = $name; } /** * Converts the object to a string * * @return string */ public function __toString() { return $this->name; } } PK]E?*DependencyInjection/ContainerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; /** * ContainerInterface is the interface implemented by service container classes. * * @author Fabien Potencier * @author Johannes M. Schmitt * * @api */ interface ContainerInterface { const EXCEPTION_ON_INVALID_REFERENCE = 1; const NULL_ON_INVALID_REFERENCE = 2; const IGNORE_ON_INVALID_REFERENCE = 3; const SCOPE_CONTAINER = 'container'; const SCOPE_PROTOTYPE = 'prototype'; /** * Sets a service. * * @param string $id The service identifier * @param object $service The service instance * @param string $scope The scope of the service * * @api */ public function set($id, $service, $scope = self::SCOPE_CONTAINER); /** * Gets a service. * * @param string $id The service identifier * @param int $invalidBehavior The behavior when the service does not exist * * @return object The associated service * * @throws InvalidArgumentException if the service is not defined * @throws ServiceCircularReferenceException When a circular reference is detected * @throws ServiceNotFoundException When the service is not defined * * @see Reference * * @api */ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE); /** * Returns true if the given service is defined. * * @param string $id The service identifier * * @return Boolean true if the service is defined, false otherwise * * @api */ public function has($id); /** * Gets a parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws InvalidArgumentException if the parameter is not defined * * @api */ public function getParameter($name); /** * Checks if a parameter exists. * * @param string $name The parameter name * * @return Boolean The presence of parameter in container * * @api */ public function hasParameter($name); /** * Sets a parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function setParameter($name, $value); /** * Enters the given scope * * @param string $name * * @api */ public function enterScope($name); /** * Leaves the current scope, and re-enters the parent scope * * @param string $name * * @api */ public function leaveScope($name); /** * Adds a scope to the container * * @param ScopeInterface $scope * * @api */ public function addScope(ScopeInterface $scope); /** * Whether this container has the given scope * * @param string $name * * @return Boolean * * @api */ public function hasScope($name); /** * Determines whether the given scope is currently active. * * It does however not check if the scope actually exists. * * @param string $name * * @return Boolean * * @api */ public function isScopeActive($name); } PK]] I I (DependencyInjection/SimpleXMLElement.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\ExpressionLanguage\Expression; /** * SimpleXMLElement class. * * @author Fabien Potencier */ class SimpleXMLElement extends \SimpleXMLElement { /** * Converts an attribute as a PHP type. * * @param string $name * * @return mixed */ public function getAttributeAsPhp($name) { return self::phpize($this[$name]); } /** * Returns arguments as valid PHP types. * * @param string $name * @param Boolean $lowercase * * @return mixed */ public function getArgumentsAsPhp($name, $lowercase = true) { $arguments = array(); foreach ($this->$name as $arg) { if (isset($arg['name'])) { $arg['key'] = (string) $arg['name']; } $key = isset($arg['key']) ? (string) $arg['key'] : (!$arguments ? 0 : max(array_keys($arguments)) + 1); // parameter keys are case insensitive if ('parameter' == $name && $lowercase) { $key = strtolower($key); } // this is used by DefinitionDecorator to overwrite a specific // argument of the parent definition if (isset($arg['index'])) { $key = 'index_'.$arg['index']; } switch ($arg['type']) { case 'service': $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; if (isset($arg['on-invalid']) && 'ignore' == $arg['on-invalid']) { $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; } elseif (isset($arg['on-invalid']) && 'null' == $arg['on-invalid']) { $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; } if (isset($arg['strict'])) { $strict = self::phpize($arg['strict']); } else { $strict = true; } $arguments[$key] = new Reference((string) $arg['id'], $invalidBehavior, $strict); break; case 'expression': $arguments[$key] = new Expression((string) $arg); break; case 'collection': $arguments[$key] = $arg->getArgumentsAsPhp($name, false); break; case 'string': $arguments[$key] = (string) $arg; break; case 'constant': $arguments[$key] = constant((string) $arg); break; default: $arguments[$key] = self::phpize($arg); } } return $arguments; } /** * Converts an xml value to a PHP type. * * @param mixed $value * * @return mixed */ public static function phpize($value) { return XmlUtils::phpize($value); } } PK]U穌PP+DependencyInjection/DefinitionDecorator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; /** * This definition decorates another definition. * * @author Johannes M. Schmitt * * @api */ class DefinitionDecorator extends Definition { private $parent; private $changes = array(); /** * Constructor. * * @param string $parent The id of Definition instance to decorate. * * @api */ public function __construct($parent) { parent::__construct(); $this->parent = $parent; } /** * Returns the Definition being decorated. * * @return string * * @api */ public function getParent() { return $this->parent; } /** * Returns all changes tracked for the Definition object. * * @return array An array of changes for this Definition * * @api */ public function getChanges() { return $this->changes; } /** * {@inheritDoc} * * @api */ public function setClass($class) { $this->changes['class'] = true; return parent::setClass($class); } /** * {@inheritDoc} * * @api */ public function setFactoryClass($class) { $this->changes['factory_class'] = true; return parent::setFactoryClass($class); } /** * {@inheritDoc} * * @api */ public function setFactoryMethod($method) { $this->changes['factory_method'] = true; return parent::setFactoryMethod($method); } /** * {@inheritDoc} * * @api */ public function setFactoryService($service) { $this->changes['factory_service'] = true; return parent::setFactoryService($service); } /** * {@inheritDoc} * * @api */ public function setConfigurator($callable) { $this->changes['configurator'] = true; return parent::setConfigurator($callable); } /** * {@inheritDoc} * * @api */ public function setFile($file) { $this->changes['file'] = true; return parent::setFile($file); } /** * {@inheritDoc} * * @api */ public function setPublic($boolean) { $this->changes['public'] = true; return parent::setPublic($boolean); } /** * {@inheritDoc} * * @api */ public function setLazy($boolean) { $this->changes['lazy'] = true; return parent::setLazy($boolean); } /** * Gets an argument to pass to the service constructor/factory method. * * If replaceArgument() has been used to replace an argument, this method * will return the replacement value. * * @param integer $index * * @return mixed The argument value * * @throws OutOfBoundsException When the argument does not exist * * @api */ public function getArgument($index) { if (array_key_exists('index_'.$index, $this->arguments)) { return $this->arguments['index_'.$index]; } $lastIndex = count(array_filter(array_keys($this->arguments), 'is_int')) - 1; if ($index < 0 || $index > $lastIndex) { throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, $lastIndex)); } return $this->arguments[$index]; } /** * You should always use this method when overwriting existing arguments * of the parent definition. * * If you directly call setArguments() keep in mind that you must follow * certain conventions when you want to overwrite the arguments of the * parent definition, otherwise your arguments will only be appended. * * @param integer $index * @param mixed $value * * @return DefinitionDecorator the current instance * @throws InvalidArgumentException when $index isn't an integer * * @api */ public function replaceArgument($index, $value) { if (!is_int($index)) { throw new InvalidArgumentException('$index must be an integer.'); } $this->arguments['index_'.$index] = $value; return $this; } } PK]LFFCDependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; /** * Replaces aliases with actual service definitions, effectively removing these * aliases. * * @author Johannes M. Schmitt */ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface { private $compiler; private $formatter; private $sourceId; /** * Process the Container to replace aliases with service definitions. * * @param ContainerBuilder $container * * @throws InvalidArgumentException if the service definition does not exist */ public function process(ContainerBuilder $container) { $this->compiler = $container->getCompiler(); $this->formatter = $this->compiler->getLoggingFormatter(); foreach ($container->getAliases() as $id => $alias) { $aliasId = (string) $alias; try { $definition = $container->getDefinition($aliasId); } catch (InvalidArgumentException $e) { throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with "%s".', $alias, $id), null, $e); } if ($definition->isPublic()) { continue; } $definition->setPublic(true); $container->setDefinition($id, $definition); $container->removeDefinition($aliasId); $this->updateReferences($container, $aliasId, $id); // we have to restart the process due to concurrent modification of // the container $this->process($container); break; } } /** * Updates references to remove aliases. * * @param ContainerBuilder $container The container * @param string $currentId The alias identifier being replaced * @param string $newId The id of the service the alias points to */ private function updateReferences($container, $currentId, $newId) { foreach ($container->getAliases() as $id => $alias) { if ($currentId === (string) $alias) { $container->setAlias($id, $newId); } } foreach ($container->getDefinitions() as $id => $definition) { $this->sourceId = $id; $definition->setArguments( $this->updateArgumentReferences($definition->getArguments(), $currentId, $newId) ); $definition->setMethodCalls( $this->updateArgumentReferences($definition->getMethodCalls(), $currentId, $newId) ); $definition->setProperties( $this->updateArgumentReferences($definition->getProperties(), $currentId, $newId) ); } } /** * Updates argument references. * * @param array $arguments An array of Arguments * @param string $currentId The alias identifier * @param string $newId The identifier the alias points to * * @return array */ private function updateArgumentReferences(array $arguments, $currentId, $newId) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->updateArgumentReferences($argument, $currentId, $newId); } elseif ($argument instanceof Reference) { if ($currentId === (string) $argument) { $arguments[$k] = new Reference($newId, $argument->getInvalidBehavior()); $this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $this->sourceId, $currentId, $newId)); } } } return $arguments; } } PK][ :DependencyInjection/Compiler/ServiceReferenceGraphNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Alias; /** * Represents a node in your service graph. * * Value is typically a definition, or an alias. * * @author Johannes M. Schmitt */ class ServiceReferenceGraphNode { private $id; private $inEdges = array(); private $outEdges = array(); private $value; /** * Constructor. * * @param string $id The node identifier * @param mixed $value The node value */ public function __construct($id, $value) { $this->id = $id; $this->value = $value; } /** * Adds an in edge to this node. * * @param ServiceReferenceGraphEdge $edge */ public function addInEdge(ServiceReferenceGraphEdge $edge) { $this->inEdges[] = $edge; } /** * Adds an out edge to this node. * * @param ServiceReferenceGraphEdge $edge */ public function addOutEdge(ServiceReferenceGraphEdge $edge) { $this->outEdges[] = $edge; } /** * Checks if the value of this node is an Alias. * * @return Boolean True if the value is an Alias instance */ public function isAlias() { return $this->value instanceof Alias; } /** * Checks if the value of this node is a Definition. * * @return Boolean True if the value is a Definition instance */ public function isDefinition() { return $this->value instanceof Definition; } /** * Returns the identifier. * * @return string */ public function getId() { return $this->id; } /** * Returns the in edges. * * @return array The in ServiceReferenceGraphEdge array */ public function getInEdges() { return $this->inEdges; } /** * Returns the out edges. * * @return array The out ServiceReferenceGraphEdge array */ public function getOutEdges() { return $this->outEdges; } /** * Returns the value of this Node * * @return mixed The value */ public function getValue() { return $this->value; } } PK]dd<DependencyInjection/Compiler/CheckDefinitionValidityPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * This pass validates each definition individually only taking the information * into account which is contained in the definition itself. * * Later passes can rely on the following, and specifically do not need to * perform these checks themselves: * * - non synthetic, non abstract services always have a class set * - synthetic services are always public * - synthetic services are always of non-prototype scope * * @author Johannes M. Schmitt */ class CheckDefinitionValidityPass implements CompilerPassInterface { /** * Processes the ContainerBuilder to validate the Definition. * * @param ContainerBuilder $container * * @throws RuntimeException When the Definition is invalid */ public function process(ContainerBuilder $container) { foreach ($container->getDefinitions() as $id => $definition) { // synthetic service is public if ($definition->isSynthetic() && !$definition->isPublic()) { throw new RuntimeException(sprintf( 'A synthetic service ("%s") must be public.', $id )); } // synthetic service has non-prototype scope if ($definition->isSynthetic() && ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) { throw new RuntimeException(sprintf( 'A synthetic service ("%s") cannot be of scope "prototype".', $id )); } // non-synthetic, non-abstract service has class if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) { if ($definition->getFactoryClass() || $definition->getFactoryService()) { throw new RuntimeException(sprintf( 'Please add the class to service "%s" even if it is constructed by a factory ' .'since we might need to add method calls based on compile-time checks.', $id )); } throw new RuntimeException(sprintf( 'The definition for "%s" has no class. If you intend to inject ' .'this service dynamically at runtime, please mark it as synthetic=true. ' .'If this is an abstract definition solely used by child definitions, ' .'please add abstract=true, otherwise specify a class to get rid of this error.', $id )); } // tag attribute values must be scalars foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { foreach ($attributes as $attribute => $value) { if (!is_scalar($value) && null !== $value) { throw new RuntimeException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $name, $attribute)); } } } } } } } PK]iJT =DependencyInjection/Compiler/ResolveInvalidReferencesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * Emulates the invalid behavior if the reference is not found within the * container. * * @author Johannes M. Schmitt */ class ResolveInvalidReferencesPass implements CompilerPassInterface { private $container; /** * Process the ContainerBuilder to resolve invalid references. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $definition->setArguments( $this->processArguments($definition->getArguments()) ); $calls = array(); foreach ($definition->getMethodCalls() as $call) { try { $calls[] = array($call[0], $this->processArguments($call[1], true)); } catch (RuntimeException $ignore) { // this call is simply removed } } $definition->setMethodCalls($calls); $properties = array(); foreach ($definition->getProperties() as $name => $value) { try { $value = $this->processArguments(array($value), true); $properties[$name] = reset($value); } catch (RuntimeException $ignore) { // ignore property } } $definition->setProperties($properties); } } /** * Processes arguments to determine invalid references. * * @param array $arguments An array of Reference objects * @param Boolean $inMethodCall * * @return array * * @throws RuntimeException When the config is invalid */ private function processArguments(array $arguments, $inMethodCall = false) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->processArguments($argument, $inMethodCall); } elseif ($argument instanceof Reference) { $id = (string) $argument; $invalidBehavior = $argument->getInvalidBehavior(); $exists = $this->container->has($id); // resolve invalid behavior if (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) { $arguments[$k] = null; } elseif (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) { if ($inMethodCall) { throw new RuntimeException('Method shouldn\'t be called.'); } $arguments[$k] = null; } } } return $arguments; } } PK]X\\@DependencyInjection/Compiler/MergeExtensionConfigurationPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; /** * Merges extension configs into the container builder * * @author Fabien Potencier */ class MergeExtensionConfigurationPass implements CompilerPassInterface { /** * {@inheritDoc} */ public function process(ContainerBuilder $container) { $parameters = $container->getParameterBag()->all(); $definitions = $container->getDefinitions(); $aliases = $container->getAliases(); foreach ($container->getExtensions() as $extension) { if ($extension instanceof PrependExtensionInterface) { $extension->prepend($container); } } foreach ($container->getExtensions() as $name => $extension) { if (!$config = $container->getExtensionConfig($name)) { // this extension was not called continue; } $config = $container->getParameterBag()->resolveValue($config); $tmpContainer = new ContainerBuilder($container->getParameterBag()); $tmpContainer->setResourceTracking($container->isTrackingResources()); $tmpContainer->addObjectResource($extension); $extension->load($config, $tmpContainer); $container->merge($tmpContainer); } $container->addDefinitions($definitions); $container->addAliases($aliases); $container->getParameterBag()->add($parameters); } } PK]V%) ) 6DependencyInjection/Compiler/ServiceReferenceGraph.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * This is a directed graph of your services. * * This information can be used by your compiler passes instead of collecting * it themselves which improves performance quite a lot. * * @author Johannes M. Schmitt */ class ServiceReferenceGraph { /** * @var ServiceReferenceGraphNode[] */ private $nodes = array(); /** * Checks if the graph has a specific node. * * @param string $id Id to check * * @return Boolean */ public function hasNode($id) { return isset($this->nodes[$id]); } /** * Gets a node by identifier. * * @param string $id The id to retrieve * * @return ServiceReferenceGraphNode The node matching the supplied identifier * * @throws InvalidArgumentException if no node matches the supplied identifier */ public function getNode($id) { if (!isset($this->nodes[$id])) { throw new InvalidArgumentException(sprintf('There is no node with id "%s".', $id)); } return $this->nodes[$id]; } /** * Returns all nodes. * * @return ServiceReferenceGraphNode[] An array of all ServiceReferenceGraphNode objects */ public function getNodes() { return $this->nodes; } /** * Clears all nodes. */ public function clear() { $this->nodes = array(); } /** * Connects 2 nodes together in the Graph. * * @param string $sourceId * @param string $sourceValue * @param string $destId * @param string $destValue * @param string $reference */ public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null) { $sourceNode = $this->createNode($sourceId, $sourceValue); $destNode = $this->createNode($destId, $destValue); $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference); $sourceNode->addOutEdge($edge); $destNode->addInEdge($edge); } /** * Creates a graph node. * * @param string $id * @param string $value * * @return ServiceReferenceGraphNode */ private function createNode($id, $value) { if (isset($this->nodes[$id]) && $this->nodes[$id]->getValue() === $value) { return $this->nodes[$id]; } return $this->nodes[$id] = new ServiceReferenceGraphNode($id, $value); } } PK]!?9DependencyInjection/Compiler/RemovePrivateAliasesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Remove private aliases from the container. They were only used to establish * dependencies between services, and these dependencies have been resolved in * one of the previous passes. * * @author Johannes M. Schmitt */ class RemovePrivateAliasesPass implements CompilerPassInterface { /** * Removes private aliases from the ContainerBuilder * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $compiler = $container->getCompiler(); $formatter = $compiler->getLoggingFormatter(); foreach ($container->getAliases() as $id => $alias) { if ($alias->isPublic()) { continue; } $container->removeAlias($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'private alias')); } } } PK]Eų8DependencyInjection/Compiler/RepeatablePassInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; /** * Interface that must be implemented by passes that are run as part of an * RepeatedPass. * * @author Johannes M. Schmitt */ interface RepeatablePassInterface extends CompilerPassInterface { /** * Sets the RepeatedPass interface. * * @param RepeatedPass $repeatedPass */ public function setRepeatedPass(RepeatedPass $repeatedPass); } PK]nnADependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; /** * Resolves all parameter placeholders "%somevalue%" to their real values. * * @author Johannes M. Schmitt */ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface { /** * Processes the ContainerBuilder to resolve parameter placeholders. * * @param ContainerBuilder $container * * @throws ParameterNotFoundException */ public function process(ContainerBuilder $container) { $parameterBag = $container->getParameterBag(); foreach ($container->getDefinitions() as $id => $definition) { try { $definition->setClass($parameterBag->resolveValue($definition->getClass())); $definition->setFile($parameterBag->resolveValue($definition->getFile())); $definition->setArguments($parameterBag->resolveValue($definition->getArguments())); $calls = array(); foreach ($definition->getMethodCalls() as $name => $arguments) { $calls[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($arguments); } $definition->setMethodCalls($calls); $definition->setProperties($parameterBag->resolveValue($definition->getProperties())); } catch (ParameterNotFoundException $e) { $e->setSourceId($id); throw $e; } } $aliases = array(); foreach ($container->getAliases() as $name => $target) { $aliases[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($target); } $container->setAliases($aliases); $parameterBag->resolve(); } } PK]b[_66MDependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Checks that all references are pointing to a valid service. * * @author Johannes M. Schmitt */ class CheckExceptionOnInvalidReferenceBehaviorPass implements CompilerPassInterface { private $container; private $sourceId; public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $id => $definition) { $this->sourceId = $id; $this->processDefinition($definition); } } private function processDefinition(Definition $definition) { $this->processReferences($definition->getArguments()); $this->processReferences($definition->getMethodCalls()); $this->processReferences($definition->getProperties()); } private function processReferences(array $arguments) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->processReferences($argument); } elseif ($argument instanceof Definition) { $this->processDefinition($argument); } elseif ($argument instanceof Reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $argument->getInvalidBehavior()) { $destId = (string) $argument; if (!$this->container->has($destId)) { throw new ServiceNotFoundException($destId, $this->sourceId); } } } } } PK]Gp5 5 )DependencyInjection/Compiler/Compiler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * This class is used to remove circular dependencies between individual passes. * * @author Johannes M. Schmitt * * @api */ class Compiler { private $passConfig; private $log = array(); private $loggingFormatter; private $serviceReferenceGraph; /** * Constructor. */ public function __construct() { $this->passConfig = new PassConfig(); $this->serviceReferenceGraph = new ServiceReferenceGraph(); $this->loggingFormatter = new LoggingFormatter(); } /** * Returns the PassConfig. * * @return PassConfig The PassConfig instance * * @api */ public function getPassConfig() { return $this->passConfig; } /** * Returns the ServiceReferenceGraph. * * @return ServiceReferenceGraph The ServiceReferenceGraph instance * * @api */ public function getServiceReferenceGraph() { return $this->serviceReferenceGraph; } /** * Returns the logging formatter which can be used by compilation passes. * * @return LoggingFormatter */ public function getLoggingFormatter() { return $this->loggingFormatter; } /** * Adds a pass to the PassConfig. * * @param CompilerPassInterface $pass A compiler pass * @param string $type The type of the pass * * @api */ public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION) { $this->passConfig->addPass($pass, $type); } /** * Adds a log message. * * @param string $string The log message */ public function addLogMessage($string) { $this->log[] = $string; } /** * Returns the log. * * @return array Log array */ public function getLog() { return $this->log; } /** * Run the Compiler and process all Passes. * * @param ContainerBuilder $container * * @api */ public function compile(ContainerBuilder $container) { foreach ($this->passConfig->getPasses() as $pass) { $pass->process($container); } } } PK]C\Z+DependencyInjection/Compiler/PassConfig.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * Compiler Pass Configuration * * This class has a default configuration embedded. * * @author Johannes M. Schmitt * * @api */ class PassConfig { const TYPE_AFTER_REMOVING = 'afterRemoving'; const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization'; const TYPE_BEFORE_REMOVING = 'beforeRemoving'; const TYPE_OPTIMIZE = 'optimization'; const TYPE_REMOVE = 'removing'; private $mergePass; private $afterRemovingPasses = array(); private $beforeOptimizationPasses = array(); private $beforeRemovingPasses = array(); private $optimizationPasses; private $removingPasses; /** * Constructor. */ public function __construct() { $this->mergePass = new MergeExtensionConfigurationPass(); $this->optimizationPasses = array( new ResolveDefinitionTemplatesPass(), new ResolveParameterPlaceHoldersPass(), new CheckDefinitionValidityPass(), new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), new AnalyzeServiceReferencesPass(true), new CheckCircularReferencesPass(), new CheckReferenceValidityPass(), ); $this->removingPasses = array( new RemovePrivateAliasesPass(), new RemoveAbstractDefinitionsPass(), new ReplaceAliasByActualDefinitionPass(), new RepeatedPass(array( new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass(), new AnalyzeServiceReferencesPass(), new RemoveUnusedDefinitionsPass(), )), new CheckExceptionOnInvalidReferenceBehaviorPass(), ); } /** * Returns all passes in order to be processed. * * @return array An array of all passes to process * * @api */ public function getPasses() { return array_merge( array($this->mergePass), $this->beforeOptimizationPasses, $this->optimizationPasses, $this->beforeRemovingPasses, $this->removingPasses, $this->afterRemovingPasses ); } /** * Adds a pass. * * @param CompilerPassInterface $pass A Compiler pass * @param string $type The pass type * * @throws InvalidArgumentException when a pass type doesn't exist * * @api */ public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION) { $property = $type.'Passes'; if (!isset($this->$property)) { throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type)); } $passes = &$this->$property; $passes[] = $pass; } /** * Gets all passes for the AfterRemoving pass. * * @return array An array of passes * * @api */ public function getAfterRemovingPasses() { return $this->afterRemovingPasses; } /** * Gets all passes for the BeforeOptimization pass. * * @return array An array of passes * * @api */ public function getBeforeOptimizationPasses() { return $this->beforeOptimizationPasses; } /** * Gets all passes for the BeforeRemoving pass. * * @return array An array of passes * * @api */ public function getBeforeRemovingPasses() { return $this->beforeRemovingPasses; } /** * Gets all passes for the Optimization pass. * * @return array An array of passes * * @api */ public function getOptimizationPasses() { return $this->optimizationPasses; } /** * Gets all passes for the Removing pass. * * @return array An array of passes * * @api */ public function getRemovingPasses() { return $this->removingPasses; } /** * Gets all passes for the Merge pass. * * @return array An array of passes * * @api */ public function getMergePass() { return $this->mergePass; } /** * Sets the Merge Pass. * * @param CompilerPassInterface $pass The merge pass * * @api */ public function setMergePass(CompilerPassInterface $pass) { $this->mergePass = $pass; } /** * Sets the AfterRemoving passes. * * @param array $passes An array of passes * * @api */ public function setAfterRemovingPasses(array $passes) { $this->afterRemovingPasses = $passes; } /** * Sets the BeforeOptimization passes. * * @param array $passes An array of passes * * @api */ public function setBeforeOptimizationPasses(array $passes) { $this->beforeOptimizationPasses = $passes; } /** * Sets the BeforeRemoving passes. * * @param array $passes An array of passes * * @api */ public function setBeforeRemovingPasses(array $passes) { $this->beforeRemovingPasses = $passes; } /** * Sets the Optimization passes. * * @param array $passes An array of passes * * @api */ public function setOptimizationPasses(array $passes) { $this->optimizationPasses = $passes; } /** * Sets the Removing passes. * * @param array $passes An array of passes * * @api */ public function setRemovingPasses(array $passes) { $this->removingPasses = $passes; } } PK]ϒ?DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * This replaces all DefinitionDecorator instances with their equivalent fully * merged Definition instance. * * @author Johannes M. Schmitt */ class ResolveDefinitionTemplatesPass implements CompilerPassInterface { private $container; private $compiler; private $formatter; /** * Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; $this->compiler = $container->getCompiler(); $this->formatter = $this->compiler->getLoggingFormatter(); foreach (array_keys($container->getDefinitions()) as $id) { // yes, we are specifically fetching the definition from the // container to ensure we are not operating on stale data $definition = $container->getDefinition($id); if (!$definition instanceof DefinitionDecorator || $definition->isAbstract()) { continue; } $this->resolveDefinition($id, $definition); } } /** * Resolves the definition * * @param string $id The definition identifier * @param DefinitionDecorator $definition * * @return Definition * * @throws \RuntimeException When the definition is invalid */ private function resolveDefinition($id, DefinitionDecorator $definition) { if (!$this->container->hasDefinition($parent = $definition->getParent())) { throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $id)); } $parentDef = $this->container->getDefinition($parent); if ($parentDef instanceof DefinitionDecorator) { $parentDef = $this->resolveDefinition($parent, $parentDef); } $this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $id, $parent)); $def = new Definition(); // merge in parent definition // purposely ignored attributes: scope, abstract, tags $def->setClass($parentDef->getClass()); $def->setArguments($parentDef->getArguments()); $def->setMethodCalls($parentDef->getMethodCalls()); $def->setProperties($parentDef->getProperties()); $def->setFactoryClass($parentDef->getFactoryClass()); $def->setFactoryMethod($parentDef->getFactoryMethod()); $def->setFactoryService($parentDef->getFactoryService()); $def->setConfigurator($parentDef->getConfigurator()); $def->setFile($parentDef->getFile()); $def->setPublic($parentDef->isPublic()); $def->setLazy($parentDef->isLazy()); // overwrite with values specified in the decorator $changes = $definition->getChanges(); if (isset($changes['class'])) { $def->setClass($definition->getClass()); } if (isset($changes['factory_class'])) { $def->setFactoryClass($definition->getFactoryClass()); } if (isset($changes['factory_method'])) { $def->setFactoryMethod($definition->getFactoryMethod()); } if (isset($changes['factory_service'])) { $def->setFactoryService($definition->getFactoryService()); } if (isset($changes['configurator'])) { $def->setConfigurator($definition->getConfigurator()); } if (isset($changes['file'])) { $def->setFile($definition->getFile()); } if (isset($changes['public'])) { $def->setPublic($definition->isPublic()); } if (isset($changes['lazy'])) { $def->setLazy($definition->isLazy()); } // merge arguments foreach ($definition->getArguments() as $k => $v) { if (is_numeric($k)) { $def->addArgument($v); continue; } if (0 !== strpos($k, 'index_')) { throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k)); } $index = (integer) substr($k, strlen('index_')); $def->replaceArgument($index, $v); } // merge properties foreach ($definition->getProperties() as $k => $v) { $def->setProperty($k, $v); } // append method calls if (count($calls = $definition->getMethodCalls()) > 0) { $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); } // these attributes are always taken from the child $def->setAbstract($definition->isAbstract()); $def->setScope($definition->getScope()); $def->setTags($definition->getTags()); // set new definition on container $this->container->setDefinition($id, $def); return $def; } } PK]iZ <DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Removes unused service definitions from the container. * * @author Johannes M. Schmitt */ class RemoveUnusedDefinitionsPass implements RepeatablePassInterface { private $repeatedPass; /** * {@inheritDoc} */ public function setRepeatedPass(RepeatedPass $repeatedPass) { $this->repeatedPass = $repeatedPass; } /** * Processes the ContainerBuilder to remove unused definitions. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $compiler = $container->getCompiler(); $formatter = $compiler->getLoggingFormatter(); $graph = $compiler->getServiceReferenceGraph(); $hasChanged = false; foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isPublic()) { continue; } if ($graph->hasNode($id)) { $edges = $graph->getNode($id)->getInEdges(); $referencingAliases = array(); $sourceIds = array(); foreach ($edges as $edge) { $node = $edge->getSourceNode(); $sourceIds[] = $node->getId(); if ($node->isAlias()) { $referencingAliases[] = $node->getValue(); } } $isReferenced = (count(array_unique($sourceIds)) - count($referencingAliases)) > 0; } else { $referencingAliases = array(); $isReferenced = false; } if (1 === count($referencingAliases) && false === $isReferenced) { $container->setDefinition((string) reset($referencingAliases), $definition); $definition->setPublic(true); $container->removeDefinition($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'replaces alias '.reset($referencingAliases))); } elseif (0 === count($referencingAliases) && false === $isReferenced) { $container->removeDefinition($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'unused')); $hasChanged = true; } } if ($hasChanged) { $this->repeatedPass->setRepeat(); } } } PK]1DependencyInjection/Compiler/LoggingFormatter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; /** * Used to format logging messages during the compilation. * * @author Johannes M. Schmitt */ class LoggingFormatter { public function formatRemoveService(CompilerPassInterface $pass, $id, $reason) { return $this->format($pass, sprintf('Removed service "%s"; reason: %s', $id, $reason)); } public function formatInlineService(CompilerPassInterface $pass, $id, $target) { return $this->format($pass, sprintf('Inlined service "%s" to "%s".', $id, $target)); } public function formatUpdateReference(CompilerPassInterface $pass, $serviceId, $oldDestId, $newDestId) { return $this->format($pass, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $serviceId, $oldDestId, $newDestId)); } public function formatResolveInheritance(CompilerPassInterface $pass, $childId, $parentId) { return $this->format($pass, sprintf('Resolving inheritance for "%s" (parent: %s).', $childId, $parentId)); } public function format(CompilerPassInterface $pass, $message) { return sprintf('%s: %s', get_class($pass), $message); } } PK]U*''>DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Removes abstract Definitions * */ class RemoveAbstractDefinitionsPass implements CompilerPassInterface { /** * Removes abstract definitions from the ContainerBuilder * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $compiler = $container->getCompiler(); $formatter = $compiler->getLoggingFormatter(); foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isAbstract()) { $container->removeDefinition($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'abstract')); } } } } PK]0є##-DependencyInjection/Compiler/RepeatedPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * A pass that might be run repeatedly. * * @author Johannes M. Schmitt */ class RepeatedPass implements CompilerPassInterface { /** * @var Boolean */ private $repeat = false; /** * @var RepeatablePassInterface[] */ private $passes; /** * Constructor. * * @param RepeatablePassInterface[] $passes An array of RepeatablePassInterface objects * * @throws InvalidArgumentException when the passes don't implement RepeatablePassInterface */ public function __construct(array $passes) { foreach ($passes as $pass) { if (!$pass instanceof RepeatablePassInterface) { throw new InvalidArgumentException('$passes must be an array of RepeatablePassInterface.'); } $pass->setRepeatedPass($this); } $this->passes = $passes; } /** * Process the repeatable passes that run more than once. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->repeat = false; foreach ($this->passes as $pass) { $pass->process($container); } if ($this->repeat) { $this->process($container); } } /** * Sets if the pass should repeat */ public function setRepeat() { $this->repeat = true; } /** * Returns the passes * * @return RepeatablePassInterface[] An array of RepeatablePassInterface objects */ public function getPasses() { return $this->passes; } } PK]_96DependencyInjection/Compiler/CompilerPassInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Interface that must be implemented by compilation passes * * @author Johannes M. Schmitt * * @api */ interface CompilerPassInterface { /** * You can modify the container here before it is dumped to PHP code. * * @param ContainerBuilder $container * * @api */ public function process(ContainerBuilder $container); } PK]@ q q <DependencyInjection/Compiler/CheckCircularReferencesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Checks your services for circular references * * References from method calls are ignored since we might be able to resolve * these references depending on the order in which services are called. * * Circular reference from method calls will only be detected at run-time. * * @author Johannes M. Schmitt */ class CheckCircularReferencesPass implements CompilerPassInterface { private $currentId; private $currentPath; private $checkedNodes; /** * Checks the ContainerBuilder object for circular references. * * @param ContainerBuilder $container The ContainerBuilder instances */ public function process(ContainerBuilder $container) { $graph = $container->getCompiler()->getServiceReferenceGraph(); $this->checkedNodes = array(); foreach ($graph->getNodes() as $id => $node) { $this->currentId = $id; $this->currentPath = array($id); $this->checkOutEdges($node->getOutEdges()); } } /** * Checks for circular references. * * @param ServiceReferenceGraphEdge[] $edges An array of Edges * * @throws ServiceCircularReferenceException When a circular reference is found. */ private function checkOutEdges(array $edges) { foreach ($edges as $edge) { $node = $edge->getDestNode(); $id = $node->getId(); if (empty($this->checkedNodes[$id])) { $searchKey = array_search($id, $this->currentPath); $this->currentPath[] = $id; if (false !== $searchKey) { throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey)); } $this->checkOutEdges($node->getOutEdges()); $this->checkedNodes[$id] = true; array_pop($this->currentPath); } } } } PK]ۻǠ=DependencyInjection/Compiler/AnalyzeServiceReferencesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Run this pass before passes that need to know more about the relation of * your services. * * This class will populate the ServiceReferenceGraph with information. You can * retrieve the graph in other passes from the compiler. * * @author Johannes M. Schmitt */ class AnalyzeServiceReferencesPass implements RepeatablePassInterface { private $graph; private $container; private $currentId; private $currentDefinition; private $repeatedPass; private $onlyConstructorArguments; /** * Constructor. * * @param Boolean $onlyConstructorArguments Sets this Service Reference pass to ignore method calls */ public function __construct($onlyConstructorArguments = false) { $this->onlyConstructorArguments = (Boolean) $onlyConstructorArguments; } /** * {@inheritDoc} */ public function setRepeatedPass(RepeatedPass $repeatedPass) { $this->repeatedPass = $repeatedPass; } /** * Processes a ContainerBuilder object to populate the service reference graph. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; $this->graph = $container->getCompiler()->getServiceReferenceGraph(); $this->graph->clear(); foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $this->currentId = $id; $this->currentDefinition = $definition; $this->processArguments($definition->getArguments()); if (!$this->onlyConstructorArguments) { $this->processArguments($definition->getMethodCalls()); $this->processArguments($definition->getProperties()); if ($definition->getConfigurator()) { $this->processArguments(array($definition->getConfigurator())); } } } foreach ($container->getAliases() as $id => $alias) { $this->graph->connect($id, $alias, (string) $alias, $this->getDefinition((string) $alias), null); } } /** * Processes service definitions for arguments to find relationships for the service graph. * * @param array $arguments An array of Reference or Definition objects relating to service definitions */ private function processArguments(array $arguments) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->processArguments($argument); } elseif ($argument instanceof Reference) { $this->graph->connect( $this->currentId, $this->currentDefinition, $this->getDefinitionId((string) $argument), $this->getDefinition((string) $argument), $argument ); } elseif ($argument instanceof Definition) { $this->processArguments($argument->getArguments()); $this->processArguments($argument->getMethodCalls()); $this->processArguments($argument->getProperties()); } } } /** * Returns a service definition given the full name or an alias. * * @param string $id A full id or alias for a service definition. * * @return Definition|null The definition related to the supplied id */ private function getDefinition($id) { $id = $this->getDefinitionId($id); return null === $id ? null : $this->container->getDefinition($id); } private function getDefinitionId($id) { while ($this->container->hasAlias($id)) { $id = (string) $this->container->getAlias($id); } if (!$this->container->hasDefinition($id)) { return null; } return $id; } } PK] ;DependencyInjection/Compiler/CheckReferenceValidityPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ScopeCrossingInjectionException; use Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException; /** * Checks the validity of references * * The following checks are performed by this pass: * - target definitions are not abstract * - target definitions are of equal or wider scope * - target definitions are in the same scope hierarchy * * @author Johannes M. Schmitt */ class CheckReferenceValidityPass implements CompilerPassInterface { private $container; private $currentId; private $currentDefinition; private $currentScope; private $currentScopeAncestors; private $currentScopeChildren; /** * Processes the ContainerBuilder to validate References. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; $children = $this->container->getScopeChildren(); $ancestors = array(); $scopes = $this->container->getScopes(); foreach ($scopes as $name => $parent) { $ancestors[$name] = array($parent); while (isset($scopes[$parent])) { $ancestors[$name][] = $parent = $scopes[$parent]; } } foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $this->currentId = $id; $this->currentDefinition = $definition; $this->currentScope = $scope = $definition->getScope(); if (ContainerInterface::SCOPE_CONTAINER === $scope) { $this->currentScopeChildren = array_keys($scopes); $this->currentScopeAncestors = array(); } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope) { $this->currentScopeChildren = isset($children[$scope]) ? $children[$scope] : array(); $this->currentScopeAncestors = isset($ancestors[$scope]) ? $ancestors[$scope] : array(); } $this->validateReferences($definition->getArguments()); $this->validateReferences($definition->getMethodCalls()); $this->validateReferences($definition->getProperties()); } } /** * Validates an array of References. * * @param array $arguments An array of Reference objects * * @throws RuntimeException when there is a reference to an abstract definition. */ private function validateReferences(array $arguments) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->validateReferences($argument); } elseif ($argument instanceof Reference) { $targetDefinition = $this->getDefinition((string) $argument); if (null !== $targetDefinition && $targetDefinition->isAbstract()) { throw new RuntimeException(sprintf( 'The definition "%s" has a reference to an abstract definition "%s". ' .'Abstract definitions cannot be the target of references.', $this->currentId, $argument )); } $this->validateScope($argument, $targetDefinition); } } } /** * Validates the scope of a single Reference. * * @param Reference $reference * @param Definition $definition * * @throws ScopeWideningInjectionException when the definition references a service of a narrower scope * @throws ScopeCrossingInjectionException when the definition references a service of another scope hierarchy */ private function validateScope(Reference $reference, Definition $definition = null) { if (ContainerInterface::SCOPE_PROTOTYPE === $this->currentScope) { return; } if (!$reference->isStrict()) { return; } if (null === $definition) { return; } if ($this->currentScope === $scope = $definition->getScope()) { return; } $id = (string) $reference; if (in_array($scope, $this->currentScopeChildren, true)) { throw new ScopeWideningInjectionException($this->currentId, $this->currentScope, $id, $scope); } if (!in_array($scope, $this->currentScopeAncestors, true)) { throw new ScopeCrossingInjectionException($this->currentId, $this->currentScope, $id, $scope); } } /** * Returns the Definition given an id. * * @param string $id Definition identifier * * @return Definition */ private function getDefinition($id) { if (!$this->container->hasDefinition($id)) { return null; } return $this->container->getDefinition($id); } } PK]P P ?DependencyInjection/Compiler/ResolveReferencesToAliasesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Replaces all references to aliases with references to the actual service. * * @author Johannes M. Schmitt */ class ResolveReferencesToAliasesPass implements CompilerPassInterface { private $container; /** * Processes the ContainerBuilder to replace references to aliases with actual service references. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $definition->setArguments($this->processArguments($definition->getArguments())); $definition->setMethodCalls($this->processArguments($definition->getMethodCalls())); $definition->setProperties($this->processArguments($definition->getProperties())); } foreach ($container->getAliases() as $id => $alias) { $aliasId = (string) $alias; if ($aliasId !== $defId = $this->getDefinitionId($aliasId)) { $container->setAlias($id, new Alias($defId, $alias->isPublic())); } } } /** * Processes the arguments to replace aliases. * * @param array $arguments An array of References * * @return array An array of References */ private function processArguments(array $arguments) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->processArguments($argument); } elseif ($argument instanceof Reference) { $defId = $this->getDefinitionId($id = (string) $argument); if ($defId !== $id) { $arguments[$k] = new Reference($defId, $argument->getInvalidBehavior(), $argument->isStrict()); } } } return $arguments; } /** * Resolves an alias into a definition id. * * @param string $id The definition or alias id to resolve * * @return string The definition id with aliases resolved */ private function getDefinitionId($id) { while ($this->container->hasAlias($id)) { $id = (string) $this->container->getAlias($id); } return $id; } } PK]m=DependencyInjection/Compiler/InlineServiceDefinitionsPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Inline service definitions where this is possible. * * @author Johannes M. Schmitt */ class InlineServiceDefinitionsPass implements RepeatablePassInterface { private $repeatedPass; private $graph; private $compiler; private $formatter; private $currentId; /** * {@inheritDoc} */ public function setRepeatedPass(RepeatedPass $repeatedPass) { $this->repeatedPass = $repeatedPass; } /** * Processes the ContainerBuilder for inline service definitions. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->compiler = $container->getCompiler(); $this->formatter = $this->compiler->getLoggingFormatter(); $this->graph = $this->compiler->getServiceReferenceGraph(); foreach ($container->getDefinitions() as $id => $definition) { $this->currentId = $id; $definition->setArguments( $this->inlineArguments($container, $definition->getArguments()) ); $definition->setMethodCalls( $this->inlineArguments($container, $definition->getMethodCalls()) ); $definition->setProperties( $this->inlineArguments($container, $definition->getProperties()) ); } } /** * Processes inline arguments. * * @param ContainerBuilder $container The ContainerBuilder * @param array $arguments An array of arguments * * @return array */ private function inlineArguments(ContainerBuilder $container, array $arguments) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->inlineArguments($container, $argument); } elseif ($argument instanceof Reference) { if (!$container->hasDefinition($id = (string) $argument)) { continue; } if ($this->isInlineableDefinition($container, $id, $definition = $container->getDefinition($id))) { $this->compiler->addLogMessage($this->formatter->formatInlineService($this, $id, $this->currentId)); if (ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope()) { $arguments[$k] = $definition; } else { $arguments[$k] = clone $definition; } } } elseif ($argument instanceof Definition) { $argument->setArguments($this->inlineArguments($container, $argument->getArguments())); $argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls())); $argument->setProperties($this->inlineArguments($container, $argument->getProperties())); } } return $arguments; } /** * Checks if the definition is inlineable. * * @param ContainerBuilder $container * @param string $id * @param Definition $definition * * @return Boolean If the definition is inlineable */ private function isInlineableDefinition(ContainerBuilder $container, $id, Definition $definition) { if (ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) { return true; } if ($definition->isPublic() || $definition->isLazy()) { return false; } if (!$this->graph->hasNode($id)) { return true; } if ($this->currentId == $id) { return false; } $ids = array(); foreach ($this->graph->getNode($id)->getInEdges() as $edge) { $ids[] = $edge->getSourceNode()->getId(); } if (count(array_unique($ids)) > 1) { return false; } return $container->getDefinition(reset($ids))->getScope() === $definition->getScope(); } } PK]x7:DependencyInjection/Compiler/ServiceReferenceGraphEdge.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; /** * Represents an edge in your service graph. * * Value is typically a reference. * * @author Johannes M. Schmitt */ class ServiceReferenceGraphEdge { private $sourceNode; private $destNode; private $value; /** * Constructor. * * @param ServiceReferenceGraphNode $sourceNode * @param ServiceReferenceGraphNode $destNode * @param string $value */ public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null) { $this->sourceNode = $sourceNode; $this->destNode = $destNode; $this->value = $value; } /** * Returns the value of the edge * * @return ServiceReferenceGraphNode */ public function getValue() { return $this->value; } /** * Returns the source node * * @return ServiceReferenceGraphNode */ public function getSourceNode() { return $this->sourceNode; } /** * Returns the destination node * * @return ServiceReferenceGraphNode */ public function getDestNode() { return $this->destNode; } } PK]F"!DependencyInjection/Parameter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Parameter represents a parameter reference. * * @author Fabien Potencier * * @api */ class Parameter { private $id; /** * Constructor. * * @param string $id The parameter key */ public function __construct($id) { $this->id = $id; } /** * __toString. * * @return string The parameter key */ public function __toString() { return (string) $this->id; } } PK]BtBB8DependencyInjection/IntrospectableContainerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * IntrospectableContainerInterface defines additional introspection functionality * for containers, allowing logic to be implemented based on a Container's state. * * @author Evan Villemez * */ interface IntrospectableContainerInterface extends ContainerInterface { /** * Check for whether or not a service has been initialized. * * @param string $id * * @return Boolean true if the service has been initialized, false otherwise * */ public function initialized($id); } PK]ӸBj,DependencyInjection/Loader/IniFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * IniFileLoader loads parameters from INI files. * * @author Fabien Potencier */ class IniFileLoader extends FileLoader { /** * Loads a resource. * * @param mixed $file The resource * @param string $type The resource type * * @throws InvalidArgumentException When ini file is not valid */ public function load($file, $type = null) { $path = $this->locator->locate($file); $this->container->addResource(new FileResource($path)); $result = parse_ini_file($path, true); if (false === $result || array() === $result) { throw new InvalidArgumentException(sprintf('The "%s" file is not valid.', $file)); } if (isset($result['parameters']) && is_array($result['parameters'])) { foreach ($result['parameters'] as $key => $value) { $this->container->setParameter($key, $value); } } } /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null) { return is_string($resource) && 'ini' === pathinfo($resource, PATHINFO_EXTENSION); } } PK]!+++-DependencyInjection/Loader/YamlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\ExpressionLanguage\Expression; /** * YamlFileLoader loads YAML files service definitions. * * The YAML format does not support anonymous services (cf. the XML loader). * * @author Fabien Potencier */ class YamlFileLoader extends FileLoader { private $yamlParser; /** * Loads a Yaml file. * * @param mixed $file The resource * @param string $type The resource type */ public function load($file, $type = null) { $path = $this->locator->locate($file); $content = $this->loadFile($path); $this->container->addResource(new FileResource($path)); // empty file if (null === $content) { return; } // imports $this->parseImports($content, $path); // parameters if (isset($content['parameters'])) { foreach ($content['parameters'] as $key => $value) { $this->container->setParameter($key, $this->resolveServices($value)); } } // extensions $this->loadFromExtensions($content); // services $this->parseDefinitions($content, $file); } /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null) { return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION); } /** * Parses all imports * * @param array $content * @param string $file */ private function parseImports($content, $file) { if (!isset($content['imports'])) { return; } foreach ($content['imports'] as $import) { $this->setCurrentDir(dirname($file)); $this->import($import['resource'], null, isset($import['ignore_errors']) ? (Boolean) $import['ignore_errors'] : false, $file); } } /** * Parses definitions * * @param array $content * @param string $file */ private function parseDefinitions($content, $file) { if (!isset($content['services'])) { return; } foreach ($content['services'] as $id => $service) { $this->parseDefinition($id, $service, $file); } } /** * Parses a definition. * * @param string $id * @param array $service * @param string $file * * @throws InvalidArgumentException When tags are invalid */ private function parseDefinition($id, $service, $file) { if (is_string($service) && 0 === strpos($service, '@')) { $this->container->setAlias($id, substr($service, 1)); return; } elseif (isset($service['alias'])) { $public = !array_key_exists('public', $service) || (Boolean) $service['public']; $this->container->setAlias($id, new Alias($service['alias'], $public)); return; } if (isset($service['parent'])) { $definition = new DefinitionDecorator($service['parent']); } else { $definition = new Definition(); } if (isset($service['class'])) { $definition->setClass($service['class']); } if (isset($service['scope'])) { $definition->setScope($service['scope']); } if (isset($service['synthetic'])) { $definition->setSynthetic($service['synthetic']); } if (isset($service['synchronized'])) { $definition->setSynchronized($service['synchronized']); } if (isset($service['lazy'])) { $definition->setLazy($service['lazy']); } if (isset($service['public'])) { $definition->setPublic($service['public']); } if (isset($service['abstract'])) { $definition->setAbstract($service['abstract']); } if (isset($service['factory_class'])) { $definition->setFactoryClass($service['factory_class']); } if (isset($service['factory_method'])) { $definition->setFactoryMethod($service['factory_method']); } if (isset($service['factory_service'])) { $definition->setFactoryService($service['factory_service']); } if (isset($service['file'])) { $definition->setFile($service['file']); } if (isset($service['arguments'])) { $definition->setArguments($this->resolveServices($service['arguments'])); } if (isset($service['properties'])) { $definition->setProperties($this->resolveServices($service['properties'])); } if (isset($service['configurator'])) { if (is_string($service['configurator'])) { $definition->setConfigurator($service['configurator']); } else { $definition->setConfigurator(array($this->resolveServices($service['configurator'][0]), $service['configurator'][1])); } } if (isset($service['calls'])) { foreach ($service['calls'] as $call) { $args = isset($call[1]) ? $this->resolveServices($call[1]) : array(); $definition->addMethodCall($call[0], $args); } } if (isset($service['tags'])) { if (!is_array($service['tags'])) { throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s.', $id, $file)); } foreach ($service['tags'] as $tag) { if (!isset($tag['name'])) { throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in %s.', $id, $file)); } $name = $tag['name']; unset($tag['name']); foreach ($tag as $attribute => $value) { if (!is_scalar($value) && null !== $value) { throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in %s.', $id, $name, $attribute, $file)); } } $definition->addTag($name, $tag); } } $this->container->setDefinition($id, $definition); } /** * Loads a YAML file. * * @param string $file * * @return array The file content */ protected function loadFile($file) { if (!stream_is_local($file)) { throw new InvalidArgumentException(sprintf('This is not a local file "%s".', $file)); } if (!file_exists($file)) { throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file)); } if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } return $this->validate($this->yamlParser->parse(file_get_contents($file)), $file); } /** * Validates a YAML file. * * @param mixed $content * @param string $file * * @return array * * @throws InvalidArgumentException When service file is not valid */ private function validate($content, $file) { if (null === $content) { return $content; } if (!is_array($content)) { throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file)); } foreach (array_keys($content) as $namespace) { if (in_array($namespace, array('imports', 'parameters', 'services'))) { continue; } if (!$this->container->hasExtension($namespace)) { $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getAlias(); }, $this->container->getExtensions())); throw new InvalidArgumentException(sprintf( 'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $namespace, $file, $namespace, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none' )); } } return $content; } /** * Resolves services. * * @param string $value * * @return Reference */ private function resolveServices($value) { if (is_array($value)) { $value = array_map(array($this, 'resolveServices'), $value); } elseif (is_string($value) && 0 === strpos($value, '@=')) { return new Expression(substr($value, 2)); } elseif (is_string($value) && 0 === strpos($value, '@')) { if (0 === strpos($value, '@@')) { $value = substr($value, 1); $invalidBehavior = null; } elseif (0 === strpos($value, '@?')) { $value = substr($value, 2); $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; } else { $value = substr($value, 1); $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; } if ('=' === substr($value, -1)) { $value = substr($value, 0, -1); $strict = false; } else { $strict = true; } if (null !== $invalidBehavior) { $value = new Reference($value, $invalidBehavior, $strict); } } return $value; } /** * Loads from Extensions * * @param array $content */ private function loadFromExtensions($content) { foreach ($content as $namespace => $values) { if (in_array($namespace, array('imports', 'parameters', 'services'))) { continue; } if (!is_array($values)) { $values = array(); } $this->container->loadFromExtension($namespace, $values); } } } PK]z#a?DependencyInjection/Loader/schema/dic/services/services-1.0.xsdnu[ PK]Ua--)DependencyInjection/Loader/FileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader; use Symfony\Component\Config\FileLocatorInterface; /** * FileLoader is the abstract class used by all built-in loaders that are file based. * * @author Fabien Potencier */ abstract class FileLoader extends BaseFileLoader { protected $container; /** * Constructor. * * @param ContainerBuilder $container A ContainerBuilder instance * @param FileLocatorInterface $locator A FileLocator instance */ public function __construct(ContainerBuilder $container, FileLocatorInterface $locator) { $this->container = $container; parent::__construct($locator); } } PK] ,DependencyInjection/Loader/ClosureLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Loader\Loader; /** * ClosureLoader loads service definitions from a PHP closure. * * The Closure has access to the container as its first argument. * * @author Fabien Potencier */ class ClosureLoader extends Loader { private $container; /** * Constructor. * * @param ContainerBuilder $container A ContainerBuilder instance */ public function __construct(ContainerBuilder $container) { $this->container = $container; } /** * Loads a Closure. * * @param \Closure $closure The resource * @param string $type The resource type */ public function load($closure, $type = null) { call_user_func($closure, $this->container); } /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null) { return $resource instanceof \Closure; } } PK]L88,DependencyInjection/Loader/XmlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\SimpleXMLElement; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * XmlFileLoader loads XML files service definitions. * * @author Fabien Potencier */ class XmlFileLoader extends FileLoader { /** * Loads an XML file. * * @param mixed $file The resource * @param string $type The resource type */ public function load($file, $type = null) { $path = $this->locator->locate($file); $xml = $this->parseFile($path); $xml->registerXPathNamespace('container', 'http://symfony.com/schema/dic/services'); $this->container->addResource(new FileResource($path)); // anonymous services $this->processAnonymousServices($xml, $path); // imports $this->parseImports($xml, $path); // parameters $this->parseParameters($xml, $path); // extensions $this->loadFromExtensions($xml); // services $this->parseDefinitions($xml, $path); } /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null) { return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION); } /** * Parses parameters * * @param SimpleXMLElement $xml * @param string $file */ private function parseParameters(SimpleXMLElement $xml, $file) { if (!$xml->parameters) { return; } $this->container->getParameterBag()->add($xml->parameters->getArgumentsAsPhp('parameter')); } /** * Parses imports * * @param SimpleXMLElement $xml * @param string $file */ private function parseImports(SimpleXMLElement $xml, $file) { if (false === $imports = $xml->xpath('//container:imports/container:import')) { return; } foreach ($imports as $import) { $this->setCurrentDir(dirname($file)); $this->import((string) $import['resource'], null, (Boolean) $import->getAttributeAsPhp('ignore-errors'), $file); } } /** * Parses multiple definitions * * @param SimpleXMLElement $xml * @param string $file */ private function parseDefinitions(SimpleXMLElement $xml, $file) { if (false === $services = $xml->xpath('//container:services/container:service')) { return; } foreach ($services as $service) { $this->parseDefinition((string) $service['id'], $service, $file); } } /** * Parses an individual Definition * * @param string $id * @param SimpleXMLElement $service * @param string $file */ private function parseDefinition($id, $service, $file) { if ((string) $service['alias']) { $public = true; if (isset($service['public'])) { $public = $service->getAttributeAsPhp('public'); } $this->container->setAlias($id, new Alias((string) $service['alias'], $public)); return; } if (isset($service['parent'])) { $definition = new DefinitionDecorator((string) $service['parent']); } else { $definition = new Definition(); } foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'synchronized', 'lazy', 'abstract') as $key) { if (isset($service[$key])) { $method = 'set'.str_replace('-', '', $key); $definition->$method((string) $service->getAttributeAsPhp($key)); } } if ($service->file) { $definition->setFile((string) $service->file); } $definition->setArguments($service->getArgumentsAsPhp('argument')); $definition->setProperties($service->getArgumentsAsPhp('property')); if (isset($service->configurator)) { if (isset($service->configurator['function'])) { $definition->setConfigurator((string) $service->configurator['function']); } else { if (isset($service->configurator['service'])) { $class = new Reference((string) $service->configurator['service'], ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false); } else { $class = (string) $service->configurator['class']; } $definition->setConfigurator(array($class, (string) $service->configurator['method'])); } } foreach ($service->call as $call) { $definition->addMethodCall((string) $call['method'], $call->getArgumentsAsPhp('argument')); } foreach ($service->tag as $tag) { $parameters = array(); foreach ($tag->attributes() as $name => $value) { if ('name' === $name) { continue; } if (false !== strpos($name, '-') && false === strpos($name, '_') && !array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) { $parameters[$normalizedName] = SimpleXMLElement::phpize($value); } // keep not normalized key for BC too $parameters[$name] = SimpleXMLElement::phpize($value); } $definition->addTag((string) $tag['name'], $parameters); } $this->container->setDefinition($id, $definition); } /** * Parses a XML file. * * @param string $file Path to a file * * @return SimpleXMLElement * * @throws InvalidArgumentException When loading of XML file returns error */ protected function parseFile($file) { try { $dom = XmlUtils::loadFile($file, array($this, 'validateSchema')); } catch (\InvalidArgumentException $e) { throw new InvalidArgumentException(sprintf('Unable to parse file "%s".', $file), $e->getCode(), $e); } $this->validateExtensions($dom, $file); return simplexml_import_dom($dom, 'Symfony\\Component\\DependencyInjection\\SimpleXMLElement'); } /** * Processes anonymous services * * @param SimpleXMLElement $xml * @param string $file */ private function processAnonymousServices(SimpleXMLElement $xml, $file) { $definitions = array(); $count = 0; // anonymous services as arguments/properties if (false !== $nodes = $xml->xpath('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]')) { foreach ($nodes as $node) { // give it a unique name $id = sprintf('%s_%d', hash('sha256', $file), ++$count); $node['id'] = $id; $definitions[$id] = array($node->service, $file, false); $node->service['id'] = $id; } } // anonymous services "in the wild" if (false !== $nodes = $xml->xpath('//container:services/container:service[not(@id)]')) { foreach ($nodes as $node) { // give it a unique name $id = sprintf('%s_%d', hash('sha256', $file), ++$count); $node['id'] = $id; $definitions[$id] = array($node, $file, true); $node->service['id'] = $id; } } // resolve definitions krsort($definitions); foreach ($definitions as $id => $def) { // anonymous services are always private $def[0]['public'] = false; $this->parseDefinition($id, $def[0], $def[1]); $oNode = dom_import_simplexml($def[0]); if (true === $def[2]) { $nNode = new \DOMElement('_services'); $oNode->parentNode->replaceChild($nNode, $oNode); $nNode->setAttribute('id', $id); } else { $oNode->parentNode->removeChild($oNode); } } } /** * Validates a documents XML schema. * * @param \DOMDocument $dom * * @return Boolean * * @throws RuntimeException When extension references a non-existent XSD file */ public function validateSchema(\DOMDocument $dom) { $schemaLocations = array('http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd')); if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) { $items = preg_split('/\s+/', $element); for ($i = 0, $nb = count($items); $i < $nb; $i += 2) { if (!$this->container->hasExtension($items[$i])) { continue; } if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) { $path = str_replace($extension->getNamespace(), str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]); if (!is_file($path)) { throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s"', get_class($extension), $path)); } $schemaLocations[$items[$i]] = $path; } } } $tmpfiles = array(); $imports = ''; foreach ($schemaLocations as $namespace => $location) { $parts = explode('/', $location); if (0 === stripos($location, 'phar://')) { $tmpfile = tempnam(sys_get_temp_dir(), 'sf2'); if ($tmpfile) { copy($location, $tmpfile); $tmpfiles[] = $tmpfile; $parts = explode('/', str_replace('\\', '/', $tmpfile)); } } $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts)); $imports .= sprintf(' '."\n", $namespace, $location); } $source = << $imports EOF ; $valid = @$dom->schemaValidateSource($source); foreach ($tmpfiles as $tmpfile) { @unlink($tmpfile); } return $valid; } /** * Validates an extension. * * @param \DOMDocument $dom * @param string $file * * @throws InvalidArgumentException When no extension is found corresponding to a tag */ private function validateExtensions(\DOMDocument $dom, $file) { foreach ($dom->documentElement->childNodes as $node) { if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) { continue; } // can it be handled by an extension? if (!$this->container->hasExtension($node->namespaceURI)) { $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getNamespace(); }, $this->container->getExtensions())); throw new InvalidArgumentException(sprintf( 'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $node->tagName, $file, $node->namespaceURI, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none' )); } } } /** * Loads from an extension. * * @param SimpleXMLElement $xml */ private function loadFromExtensions(SimpleXMLElement $xml) { foreach (dom_import_simplexml($xml)->childNodes as $node) { if (!$node instanceof \DOMElement || $node->namespaceURI === 'http://symfony.com/schema/dic/services') { continue; } $values = static::convertDomElementToArray($node); if (!is_array($values)) { $values = array(); } $this->container->loadFromExtension($node->namespaceURI, $values); } } /** * Converts a \DomElement object to a PHP array. * * The following rules applies during the conversion: * * * Each tag is converted to a key value or an array * if there is more than one "value" * * * The content of a tag is set under a "value" key (bar) * if the tag also has some nested tags * * * The attributes are converted to keys () * * * The nested-tags are converted to keys (bar) * * @param \DomElement $element A \DomElement instance * * @return array A PHP array */ public static function convertDomElementToArray(\DomElement $element) { return XmlUtils::convertDomElementToArray($element); } } PK]((,DependencyInjection/Loader/PhpFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\Config\Resource\FileResource; /** * PhpFileLoader loads service definitions from a PHP file. * * The PHP file is required and the $container variable can be * used within the file to change the container. * * @author Fabien Potencier */ class PhpFileLoader extends FileLoader { /** * Loads a PHP file. * * @param mixed $file The resource * @param string $type The resource type */ public function load($file, $type = null) { // the container and loader variables are exposed to the included file below $container = $this->container; $loader = $this; $path = $this->locator->locate($file); $this->setCurrentDir(dirname($path)); $this->container->addResource(new FileResource($path)); include $path; } /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null) { return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION); } } PK]l.0DependencyInjection/Exception/LogicException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base LogicException for Dependency Injection component. */ class LogicException extends \LogicException implements ExceptionInterface { } PK]94DependencyInjection/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base ExceptionInterface for Dependency Injection component. * * @author Fabien Potencier * @author Bulat Shakirzyanov */ interface ExceptionInterface { } PK] +2DependencyInjection/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base RuntimeException for Dependency Injection component. * * @author Johannes M. Schmitt */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK]= ԥADependencyInjection/Exception/ScopeCrossingInjectionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when the a scope crossing injection is detected. * * @author Johannes M. Schmitt */ class ScopeCrossingInjectionException extends RuntimeException { private $sourceServiceId; private $sourceScope; private $destServiceId; private $destScope; public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null) { parent::__construct(sprintf( 'Scope Crossing Injection detected: The definition "%s" references the service "%s" which belongs to another scope hierarchy. ' .'This service might not be available consistently. Generally, it is safer to either move the definition "%s" to scope "%s", or ' .'declare "%s" as a child scope of "%s". If you can be sure that the other scope is always active, you can set the reference to strict=false to get rid of this error.', $sourceServiceId, $destServiceId, $sourceServiceId, $destScope, $sourceScope, $destScope ), 0, $previous); $this->sourceServiceId = $sourceServiceId; $this->sourceScope = $sourceScope; $this->destServiceId = $destServiceId; $this->destScope = $destScope; } public function getSourceServiceId() { return $this->sourceServiceId; } public function getSourceScope() { return $this->sourceScope; } public function getDestServiceId() { return $this->destServiceId; } public function getDestScope() { return $this->destScope; } } PK] O,8DependencyInjection/Exception/BadMethodCallException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base BadMethodCallException for Dependency Injection component. */ class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface { } PK]]CDependencyInjection/Exception/ServiceCircularReferenceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a circular reference is detected. * * @author Johannes M. Schmitt */ class ServiceCircularReferenceException extends RuntimeException { private $serviceId; private $path; public function __construct($serviceId, array $path, \Exception $previous = null) { parent::__construct(sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, implode(' -> ', $path)), 0, $previous); $this->serviceId = $serviceId; $this->path = $path; } public function getServiceId() { return $this->serviceId; } public function getPath() { return $this->path; } } PK]qBEDependencyInjection/Exception/ParameterCircularReferenceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a circular reference in a parameter is detected. * * @author Fabien Potencier */ class ParameterCircularReferenceException extends RuntimeException { private $parameters; public function __construct($parameters, \Exception $previous = null) { parent::__construct(sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], implode('" > "', $parameters), $parameters[0]), 0, $previous); $this->parameters = $parameters; } public function getParameters() { return $this->parameters; } } PK]zADependencyInjection/Exception/ScopeWideningInjectionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Thrown when a scope widening injection is detected. * * @author Johannes M. Schmitt */ class ScopeWideningInjectionException extends RuntimeException { private $sourceServiceId; private $sourceScope; private $destServiceId; private $destScope; public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null) { parent::__construct(sprintf( 'Scope Widening Injection detected: The definition "%s" references the service "%s" which belongs to a narrower scope. ' .'Generally, it is safer to either move "%s" to scope "%s" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "%s" each time it is needed. ' .'In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error.', $sourceServiceId, $destServiceId, $sourceServiceId, $destScope, $destServiceId ), 0, $previous); $this->sourceServiceId = $sourceServiceId; $this->sourceScope = $sourceScope; $this->destServiceId = $destServiceId; $this->destScope = $destScope; } public function getSourceServiceId() { return $this->sourceServiceId; } public function getSourceScope() { return $this->sourceScope; } public function getDestServiceId() { return $this->destServiceId; } public function getDestScope() { return $this->destScope; } } PK]\ <DependencyInjection/Exception/ParameterNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a non-existent parameter is used. * * @author Fabien Potencier */ class ParameterNotFoundException extends InvalidArgumentException { private $key; private $sourceId; private $sourceKey; private $alternatives; /** * Constructor. * * @param string $key The requested parameter key * @param string $sourceId The service id that references the non-existent parameter * @param string $sourceKey The parameter key that references the non-existent parameter * @param \Exception $previous The previous exception * @param string[] $alternatives Some parameter name alternatives */ public function __construct($key, $sourceId = null, $sourceKey = null, \Exception $previous = null, array $alternatives = array()) { $this->key = $key; $this->sourceId = $sourceId; $this->sourceKey = $sourceKey; $this->alternatives = $alternatives; parent::__construct('', 0, $previous); $this->updateRepr(); } public function updateRepr() { if (null !== $this->sourceId) { $this->message = sprintf('The service "%s" has a dependency on a non-existent parameter "%s".', $this->sourceId, $this->key); } elseif (null !== $this->sourceKey) { $this->message = sprintf('The parameter "%s" has a dependency on a non-existent parameter "%s".', $this->sourceKey, $this->key); } else { $this->message = sprintf('You have requested a non-existent parameter "%s".', $this->key); } if ($this->alternatives) { if (1 == count($this->alternatives)) { $this->message .= ' Did you mean this: "'; } else { $this->message .= ' Did you mean one of these: "'; } $this->message .= implode('", "', $this->alternatives).'"?'; } } public function getKey() { return $this->key; } public function getSourceId() { return $this->sourceId; } public function getSourceKey() { return $this->sourceKey; } public function setSourceId($sourceId) { $this->sourceId = $sourceId; $this->updateRepr(); } public function setSourceKey($sourceKey) { $this->sourceKey = $sourceKey; $this->updateRepr(); } } PK] :DependencyInjection/Exception/ServiceNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a non-existent service is requested. * * @author Johannes M. Schmitt */ class ServiceNotFoundException extends InvalidArgumentException { private $id; private $sourceId; public function __construct($id, $sourceId = null, \Exception $previous = null, array $alternatives = array()) { if (null === $sourceId) { $msg = sprintf('You have requested a non-existent service "%s".', $id); } else { $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id); } if ($alternatives) { if (1 == count($alternatives)) { $msg .= ' Did you mean this: "'; } else { $msg .= ' Did you mean one of these: "'; } $msg .= implode('", "', $alternatives).'"?'; } parent::__construct($msg, 0, $previous); $this->id = $id; $this->sourceId = $sourceId; } public function getId() { return $this->id; } public function getSourceId() { return $this->sourceId; } } PK]I_8DependencyInjection/Exception/InactiveScopeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when you try to create a service of an inactive scope. * * @author Johannes M. Schmitt */ class InactiveScopeException extends RuntimeException { private $serviceId; private $scope; public function __construct($serviceId, $scope, \Exception $previous = null) { parent::__construct(sprintf('You cannot create a service ("%s") of an inactive scope ("%s").', $serviceId, $scope), 0, $previous); $this->serviceId = $serviceId; $this->scope = $scope; } public function getServiceId() { return $this->serviceId; } public function getScope() { return $this->scope; } } PK]:DependencyInjection/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base InvalidArgumentException for Dependency Injection component. * * @author Bulat Shakirzyanov */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PK]{6DependencyInjection/Exception/OutOfBoundsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base OutOfBoundsException for Dependency Injection component. */ class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface { } PK]c!8989"DependencyInjection/Definition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; /** * Definition represents a service definition. * * @author Fabien Potencier * * @api */ class Definition { private $class; private $file; private $factoryClass; private $factoryMethod; private $factoryService; private $scope = ContainerInterface::SCOPE_CONTAINER; private $properties = array(); private $calls = array(); private $configurator; private $tags = array(); private $public = true; private $synthetic = false; private $abstract = false; private $synchronized = false; private $lazy = false; protected $arguments; /** * Constructor. * * @param string|null $class The service class * @param array $arguments An array of arguments to pass to the service constructor * * @api */ public function __construct($class = null, array $arguments = array()) { $this->class = $class; $this->arguments = $arguments; } /** * Sets the name of the class that acts as a factory using the factory method, * which will be invoked statically. * * @param string $factoryClass The factory class name * * @return Definition The current instance * * @api */ public function setFactoryClass($factoryClass) { $this->factoryClass = $factoryClass; return $this; } /** * Gets the factory class. * * @return string|null The factory class name * * @api */ public function getFactoryClass() { return $this->factoryClass; } /** * Sets the factory method able to create an instance of this class. * * @param string $factoryMethod The factory method name * * @return Definition The current instance * * @api */ public function setFactoryMethod($factoryMethod) { $this->factoryMethod = $factoryMethod; return $this; } /** * Gets the factory method. * * @return string|null The factory method name * * @api */ public function getFactoryMethod() { return $this->factoryMethod; } /** * Sets the name of the service that acts as a factory using the factory method. * * @param string $factoryService The factory service id * * @return Definition The current instance * * @api */ public function setFactoryService($factoryService) { $this->factoryService = $factoryService; return $this; } /** * Gets the factory service id. * * @return string|null The factory service id * * @api */ public function getFactoryService() { return $this->factoryService; } /** * Sets the service class. * * @param string $class The service class * * @return Definition The current instance * * @api */ public function setClass($class) { $this->class = $class; return $this; } /** * Gets the service class. * * @return string|null The service class * * @api */ public function getClass() { return $this->class; } /** * Sets the arguments to pass to the service constructor/factory method. * * @param array $arguments An array of arguments * * @return Definition The current instance * * @api */ public function setArguments(array $arguments) { $this->arguments = $arguments; return $this; } /** * @api */ public function setProperties(array $properties) { $this->properties = $properties; return $this; } /** * @api */ public function getProperties() { return $this->properties; } /** * @api */ public function setProperty($name, $value) { $this->properties[$name] = $value; return $this; } /** * Adds an argument to pass to the service constructor/factory method. * * @param mixed $argument An argument * * @return Definition The current instance * * @api */ public function addArgument($argument) { $this->arguments[] = $argument; return $this; } /** * Sets a specific argument * * @param integer $index * @param mixed $argument * * @return Definition The current instance * * @throws OutOfBoundsException When the replaced argument does not exist * * @api */ public function replaceArgument($index, $argument) { if ($index < 0 || $index > count($this->arguments) - 1) { throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, count($this->arguments) - 1)); } $this->arguments[$index] = $argument; return $this; } /** * Gets the arguments to pass to the service constructor/factory method. * * @return array The array of arguments * * @api */ public function getArguments() { return $this->arguments; } /** * Gets an argument to pass to the service constructor/factory method. * * @param integer $index * * @return mixed The argument value * * @throws OutOfBoundsException When the argument does not exist * * @api */ public function getArgument($index) { if ($index < 0 || $index > count($this->arguments) - 1) { throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, count($this->arguments) - 1)); } return $this->arguments[$index]; } /** * Sets the methods to call after service initialization. * * @param array $calls An array of method calls * * @return Definition The current instance * * @api */ public function setMethodCalls(array $calls = array()) { $this->calls = array(); foreach ($calls as $call) { $this->addMethodCall($call[0], $call[1]); } return $this; } /** * Adds a method to call after service initialization. * * @param string $method The method name to call * @param array $arguments An array of arguments to pass to the method call * * @return Definition The current instance * * @throws InvalidArgumentException on empty $method param * * @api */ public function addMethodCall($method, array $arguments = array()) { if (empty($method)) { throw new InvalidArgumentException(sprintf('Method name cannot be empty.')); } $this->calls[] = array($method, $arguments); return $this; } /** * Removes a method to call after service initialization. * * @param string $method The method name to remove * * @return Definition The current instance * * @api */ public function removeMethodCall($method) { foreach ($this->calls as $i => $call) { if ($call[0] === $method) { unset($this->calls[$i]); break; } } return $this; } /** * Check if the current definition has a given method to call after service initialization. * * @param string $method The method name to search for * * @return Boolean * * @api */ public function hasMethodCall($method) { foreach ($this->calls as $call) { if ($call[0] === $method) { return true; } } return false; } /** * Gets the methods to call after service initialization. * * @return array An array of method calls * * @api */ public function getMethodCalls() { return $this->calls; } /** * Sets tags for this definition * * @param array $tags * * @return Definition the current instance * * @api */ public function setTags(array $tags) { $this->tags = $tags; return $this; } /** * Returns all tags. * * @return array An array of tags * * @api */ public function getTags() { return $this->tags; } /** * Gets a tag by name. * * @param string $name The tag name * * @return array An array of attributes * * @api */ public function getTag($name) { return isset($this->tags[$name]) ? $this->tags[$name] : array(); } /** * Adds a tag for this definition. * * @param string $name The tag name * @param array $attributes An array of attributes * * @return Definition The current instance * * @api */ public function addTag($name, array $attributes = array()) { $this->tags[$name][] = $attributes; return $this; } /** * Whether this definition has a tag with the given name * * @param string $name * * @return Boolean * * @api */ public function hasTag($name) { return isset($this->tags[$name]); } /** * Clears all tags for a given name. * * @param string $name The tag name * * @return Definition */ public function clearTag($name) { if (isset($this->tags[$name])) { unset($this->tags[$name]); } return $this; } /** * Clears the tags for this definition. * * @return Definition The current instance * * @api */ public function clearTags() { $this->tags = array(); return $this; } /** * Sets a file to require before creating the service. * * @param string $file A full pathname to include * * @return Definition The current instance * * @api */ public function setFile($file) { $this->file = $file; return $this; } /** * Gets the file to require before creating the service. * * @return string|null The full pathname to include * * @api */ public function getFile() { return $this->file; } /** * Sets the scope of the service * * @param string $scope Whether the service must be shared or not * * @return Definition The current instance * * @api */ public function setScope($scope) { $this->scope = $scope; return $this; } /** * Returns the scope of the service * * @return string * * @api */ public function getScope() { return $this->scope; } /** * Sets the visibility of this service. * * @param Boolean $boolean * * @return Definition The current instance * * @api */ public function setPublic($boolean) { $this->public = (Boolean) $boolean; return $this; } /** * Whether this service is public facing * * @return Boolean * * @api */ public function isPublic() { return $this->public; } /** * Sets the synchronized flag of this service. * * @param Boolean $boolean * * @return Definition The current instance * * @api */ public function setSynchronized($boolean) { $this->synchronized = (Boolean) $boolean; return $this; } /** * Whether this service is synchronized. * * @return Boolean * * @api */ public function isSynchronized() { return $this->synchronized; } /** * Sets the lazy flag of this service. * * @param Boolean $lazy * * @return Definition The current instance */ public function setLazy($lazy) { $this->lazy = (Boolean) $lazy; return $this; } /** * Whether this service is lazy. * * @return Boolean */ public function isLazy() { return $this->lazy; } /** * Sets whether this definition is synthetic, that is not constructed by the * container, but dynamically injected. * * @param Boolean $boolean * * @return Definition the current instance * * @api */ public function setSynthetic($boolean) { $this->synthetic = (Boolean) $boolean; return $this; } /** * Whether this definition is synthetic, that is not constructed by the * container, but dynamically injected. * * @return Boolean * * @api */ public function isSynthetic() { return $this->synthetic; } /** * Whether this definition is abstract, that means it merely serves as a * template for other definitions. * * @param Boolean $boolean * * @return Definition the current instance * * @api */ public function setAbstract($boolean) { $this->abstract = (Boolean) $boolean; return $this; } /** * Whether this definition is abstract, that means it merely serves as a * template for other definitions. * * @return Boolean * * @api */ public function isAbstract() { return $this->abstract; } /** * Sets a configurator to call after the service is fully initialized. * * @param callable $callable A PHP callable * * @return Definition The current instance * * @api */ public function setConfigurator($callable) { $this->configurator = $callable; return $this; } /** * Gets the configurator to call after the service is fully initialized. * * @return callable|null The PHP callable to call * * @api */ public function getConfigurator() { return $this->configurator; } } PK]ܮP8 :DependencyInjection/ParameterBag/ParameterBagInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\ParameterBag; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; /** * ParameterBagInterface. * * @author Fabien Potencier * * @api */ interface ParameterBagInterface { /** * Clears all parameters. * * @api */ public function clear(); /** * Adds parameters to the service container parameters. * * @param array $parameters An array of parameters * * @api */ public function add(array $parameters); /** * Gets the service container parameters. * * @return array An array of parameters * * @api */ public function all(); /** * Gets a service container parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws ParameterNotFoundException if the parameter is not defined * * @api */ public function get($name); /** * Sets a service container parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function set($name, $value); /** * Returns true if a parameter name is defined. * * @param string $name The parameter name * * @return Boolean true if the parameter name is defined, false otherwise * * @api */ public function has($name); /** * Replaces parameter placeholders (%name%) by their values for all parameters. */ public function resolve(); /** * Replaces parameter placeholders (%name%) by their values. * * @param mixed $value A value * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist */ public function resolveValue($value); /** * Escape parameter placeholders % * * @param mixed $value * * @return mixed */ public function escapeValue($value); /** * Unescape parameter placeholders % * * @param mixed $value * * @return mixed */ public function unescapeValue($value); } PK]U" " 1DependencyInjection/ParameterBag/ParameterBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\ParameterBag; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * Holds parameters. * * @author Fabien Potencier * * @api */ class ParameterBag implements ParameterBagInterface { protected $parameters = array(); protected $resolved = false; /** * Constructor. * * @param array $parameters An array of parameters * * @api */ public function __construct(array $parameters = array()) { $this->add($parameters); } /** * Clears all parameters. * * @api */ public function clear() { $this->parameters = array(); } /** * Adds parameters to the service container parameters. * * @param array $parameters An array of parameters * * @api */ public function add(array $parameters) { foreach ($parameters as $key => $value) { $this->parameters[strtolower($key)] = $value; } } /** * Gets the service container parameters. * * @return array An array of parameters * * @api */ public function all() { return $this->parameters; } /** * Gets a service container parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws ParameterNotFoundException if the parameter is not defined * * @api */ public function get($name) { $name = strtolower($name); if (!array_key_exists($name, $this->parameters)) { if (!$name) { throw new ParameterNotFoundException($name); } $alternatives = array(); foreach (array_keys($this->parameters) as $key) { $lev = levenshtein($name, $key); if ($lev <= strlen($name) / 3 || false !== strpos($key, $name)) { $alternatives[] = $key; } } throw new ParameterNotFoundException($name, null, null, null, $alternatives); } return $this->parameters[$name]; } /** * Sets a service container parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function set($name, $value) { $this->parameters[strtolower($name)] = $value; } /** * Returns true if a parameter name is defined. * * @param string $name The parameter name * * @return Boolean true if the parameter name is defined, false otherwise * * @api */ public function has($name) { return array_key_exists(strtolower($name), $this->parameters); } /** * Removes a parameter. * * @param string $name The parameter name * * @api */ public function remove($name) { unset($this->parameters[strtolower($name)]); } /** * Replaces parameter placeholders (%name%) by their values for all parameters. */ public function resolve() { if ($this->resolved) { return; } $parameters = array(); foreach ($this->parameters as $key => $value) { try { $value = $this->resolveValue($value); $parameters[$key] = $this->unescapeValue($value); } catch (ParameterNotFoundException $e) { $e->setSourceKey($key); throw $e; } } $this->parameters = $parameters; $this->resolved = true; } /** * Replaces parameter placeholders (%name%) by their values. * * @param mixed $value A value * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) * * @return mixed The resolved value * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist * @throws ParameterCircularReferenceException if a circular reference if detected * @throws RuntimeException when a given parameter has a type problem. */ public function resolveValue($value, array $resolving = array()) { if (is_array($value)) { $args = array(); foreach ($value as $k => $v) { $args[$this->resolveValue($k, $resolving)] = $this->resolveValue($v, $resolving); } return $args; } if (!is_string($value)) { return $value; } return $this->resolveString($value, $resolving); } /** * Resolves parameters inside a string * * @param string $value The string to resolve * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) * * @return string The resolved string * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist * @throws ParameterCircularReferenceException if a circular reference if detected * @throws RuntimeException when a given parameter has a type problem. */ public function resolveString($value, array $resolving = array()) { // we do this to deal with non string values (Boolean, integer, ...) // as the preg_replace_callback throw an exception when trying // a non-string in a parameter value if (preg_match('/^%([^%\s]+)%$/', $value, $match)) { $key = strtolower($match[1]); if (isset($resolving[$key])) { throw new ParameterCircularReferenceException(array_keys($resolving)); } $resolving[$key] = true; return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving); } $self = $this; return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($self, $resolving, $value) { // skip %% if (!isset($match[1])) { return '%%'; } $key = strtolower($match[1]); if (isset($resolving[$key])) { throw new ParameterCircularReferenceException(array_keys($resolving)); } $resolved = $self->get($key); if (!is_string($resolved) && !is_numeric($resolved)) { throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type %s inside string value "%s".', $key, gettype($resolved), $value)); } $resolved = (string) $resolved; $resolving[$key] = true; return $self->isResolved() ? $resolved : $self->resolveString($resolved, $resolving); }, $value); } public function isResolved() { return $this->resolved; } /** * {@inheritDoc} */ public function escapeValue($value) { if (is_string($value)) { return str_replace('%', '%%', $value); } if (is_array($value)) { $result = array(); foreach ($value as $k => $v) { $result[$k] = $this->escapeValue($v); } return $result; } return $value; } public function unescapeValue($value) { if (is_string($value)) { return str_replace('%%', '%', $value); } if (is_array($value)) { $result = array(); foreach ($value as $k => $v) { $result[$k] = $this->unescapeValue($v); } return $result; } return $value; } } PK]ך7DependencyInjection/ParameterBag/FrozenParameterBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\ParameterBag; use Symfony\Component\DependencyInjection\Exception\LogicException; /** * Holds read-only parameters. * * @author Fabien Potencier * * @api */ class FrozenParameterBag extends ParameterBag { /** * Constructor. * * For performance reasons, the constructor assumes that * all keys are already lowercased. * * This is always the case when used internally. * * @param array $parameters An array of parameters * * @api */ public function __construct(array $parameters = array()) { $this->parameters = $parameters; $this->resolved = true; } /** * {@inheritDoc} * * @api */ public function clear() { throw new LogicException('Impossible to call clear() on a frozen ParameterBag.'); } /** * {@inheritDoc} * * @api */ public function add(array $parameters) { throw new LogicException('Impossible to call add() on a frozen ParameterBag.'); } /** * {@inheritDoc} * * @api */ public function set($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } } PK]q8I/DependencyInjection/ContainerAwareInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * ContainerAwareInterface should be implemented by classes that depends on a Container. * * @author Fabien Potencier * * @api */ interface ContainerAwareInterface { /** * Sets the Container. * * @param ContainerInterface|null $container A ContainerInterface instance or null * * @api */ public function setContainer(ContainerInterface $container = null); } PK]H 8+DependencyInjection/ContainerAwareTrait.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * ContainerAware trait. * * @author Fabien Potencier */ trait ContainerAwareTrait { /** * @var ContainerInterface */ protected $container; /** * Sets the Container associated with this Controller. * * @param ContainerInterface $container A ContainerInterface instance */ public function setContainer(ContainerInterface $container = null) { $this->container = $container; } } PK]uii&DependencyInjection/ContainerAware.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * A simple implementation of ContainerAwareInterface. * * @author Fabien Potencier * * @api */ abstract class ContainerAware implements ContainerAwareInterface { /** * @var ContainerInterface * * @api */ protected $container; /** * Sets the Container associated with this Controller. * * @param ContainerInterface $container A ContainerInterface instance * * @api */ public function setContainer(ContainerInterface $container = null) { $this->container = $container; } } PK]-R],,!DependencyInjection/Reference.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Reference represents a service reference. * * @author Fabien Potencier * * @api */ class Reference { private $id; private $invalidBehavior; private $strict; /** * Constructor. * * @param string $id The service identifier * @param int $invalidBehavior The behavior when the service does not exist * @param Boolean $strict Sets how this reference is validated * * @see Container */ public function __construct($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $strict = true) { $this->id = strtolower($id); $this->invalidBehavior = $invalidBehavior; $this->strict = $strict; } /** * __toString. * * @return string The service identifier */ public function __toString() { return $this->id; } /** * Returns the behavior to be used when the service does not exist. * * @return int */ public function getInvalidBehavior() { return $this->invalidBehavior; } /** * Returns true when this Reference is strict * * @return Boolean */ public function isStrict() { return $this->strict; } } PK],xmmDependencyInjection/Scope.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Scope class. * * @author Johannes M. Schmitt * * @api */ class Scope implements ScopeInterface { private $name; private $parentName; /** * @api */ public function __construct($name, $parentName = ContainerInterface::SCOPE_CONTAINER) { $this->name = $name; $this->parentName = $parentName; } /** * @api */ public function getName() { return $this->name; } /** * @api */ public function getParentName() { return $this->parentName; } } PK]-&(DependencyInjection/ContainerBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; use Symfony\Component\DependencyInjection\Exception\InactiveScopeException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; use Symfony\Component\ExpressionLanguage\Expression; /** * ContainerBuilder is a DI container that provides an API to easily describe services. * * @author Fabien Potencier * * @api */ class ContainerBuilder extends Container implements TaggedContainerInterface { /** * @var ExtensionInterface[] */ private $extensions = array(); /** * @var ExtensionInterface[] */ private $extensionsByNs = array(); /** * @var Definition[] */ private $definitions = array(); /** * @var Definition[] */ private $obsoleteDefinitions = array(); /** * @var Alias[] */ private $aliasDefinitions = array(); /** * @var ResourceInterface[] */ private $resources = array(); private $extensionConfigs = array(); /** * @var Compiler */ private $compiler; private $trackResources = true; /** * @var InstantiatorInterface|null */ private $proxyInstantiator; /** * @var ExpressionLanguage|null */ private $expressionLanguage; /** * Sets the track resources flag. * * If you are not using the loaders and therefore don't want * to depend on the Config component, set this flag to false. * * @param Boolean $track true if you want to track resources, false otherwise */ public function setResourceTracking($track) { $this->trackResources = (Boolean) $track; } /** * Checks if resources are tracked. * * @return Boolean true if resources are tracked, false otherwise */ public function isTrackingResources() { return $this->trackResources; } /** * Sets the instantiator to be used when fetching proxies. * * @param InstantiatorInterface $proxyInstantiator */ public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) { $this->proxyInstantiator = $proxyInstantiator; } /** * Registers an extension. * * @param ExtensionInterface $extension An extension instance * * @api */ public function registerExtension(ExtensionInterface $extension) { $this->extensions[$extension->getAlias()] = $extension; if (false !== $extension->getNamespace()) { $this->extensionsByNs[$extension->getNamespace()] = $extension; } } /** * Returns an extension by alias or namespace. * * @param string $name An alias or a namespace * * @return ExtensionInterface An extension instance * * @throws LogicException if the extension is not registered * * @api */ public function getExtension($name) { if (isset($this->extensions[$name])) { return $this->extensions[$name]; } if (isset($this->extensionsByNs[$name])) { return $this->extensionsByNs[$name]; } throw new LogicException(sprintf('Container extension "%s" is not registered', $name)); } /** * Returns all registered extensions. * * @return ExtensionInterface[] An array of ExtensionInterface * * @api */ public function getExtensions() { return $this->extensions; } /** * Checks if we have an extension. * * @param string $name The name of the extension * * @return Boolean If the extension exists * * @api */ public function hasExtension($name) { return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]); } /** * Returns an array of resources loaded to build this configuration. * * @return ResourceInterface[] An array of resources * * @api */ public function getResources() { return array_unique($this->resources); } /** * Adds a resource for this configuration. * * @param ResourceInterface $resource A resource instance * * @return ContainerBuilder The current instance * * @api */ public function addResource(ResourceInterface $resource) { if (!$this->trackResources) { return $this; } $this->resources[] = $resource; return $this; } /** * Sets the resources for this configuration. * * @param ResourceInterface[] $resources An array of resources * * @return ContainerBuilder The current instance * * @api */ public function setResources(array $resources) { if (!$this->trackResources) { return $this; } $this->resources = $resources; return $this; } /** * Adds the object class hierarchy as resources. * * @param object $object An object instance * * @return ContainerBuilder The current instance * * @api */ public function addObjectResource($object) { if ($this->trackResources) { $this->addClassResource(new \ReflectionClass($object)); } return $this; } /** * Adds the given class hierarchy as resources. * * @param \ReflectionClass $class * * @return ContainerBuilder The current instance */ public function addClassResource(\ReflectionClass $class) { if (!$this->trackResources) { return $this; } do { $this->addResource(new FileResource($class->getFileName())); } while ($class = $class->getParentClass()); return $this; } /** * Loads the configuration for an extension. * * @param string $extension The extension alias or namespace * @param array $values An array of values that customizes the extension * * @return ContainerBuilder The current instance * @throws BadMethodCallException When this ContainerBuilder is frozen * * @throws \LogicException if the container is frozen * * @api */ public function loadFromExtension($extension, array $values = array()) { if ($this->isFrozen()) { throw new BadMethodCallException('Cannot load from an extension on a frozen container.'); } $namespace = $this->getExtension($extension)->getAlias(); $this->extensionConfigs[$namespace][] = $values; return $this; } /** * Adds a compiler pass. * * @param CompilerPassInterface $pass A compiler pass * @param string $type The type of compiler pass * * @return ContainerBuilder The current instance * * @api */ public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION) { $this->getCompiler()->addPass($pass, $type); $this->addObjectResource($pass); return $this; } /** * Returns the compiler pass config which can then be modified. * * @return PassConfig The compiler pass config * * @api */ public function getCompilerPassConfig() { return $this->getCompiler()->getPassConfig(); } /** * Returns the compiler. * * @return Compiler The compiler * * @api */ public function getCompiler() { if (null === $this->compiler) { $this->compiler = new Compiler(); } return $this->compiler; } /** * Returns all Scopes. * * @return array An array of scopes * * @api */ public function getScopes() { return $this->scopes; } /** * Returns all Scope children. * * @return array An array of scope children. * * @api */ public function getScopeChildren() { return $this->scopeChildren; } /** * Sets a service. * * @param string $id The service identifier * @param object $service The service instance * @param string $scope The scope * * @throws BadMethodCallException When this ContainerBuilder is frozen * * @api */ public function set($id, $service, $scope = self::SCOPE_CONTAINER) { $id = strtolower($id); if ($this->isFrozen()) { // setting a synthetic service on a frozen container is alright if ( (!isset($this->definitions[$id]) && !isset($this->obsoleteDefinitions[$id])) || (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic()) || (isset($this->obsoleteDefinitions[$id]) && !$this->obsoleteDefinitions[$id]->isSynthetic()) ) { throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id)); } } if (isset($this->definitions[$id])) { $this->obsoleteDefinitions[$id] = $this->definitions[$id]; } unset($this->definitions[$id], $this->aliasDefinitions[$id]); parent::set($id, $service, $scope); if (isset($this->obsoleteDefinitions[$id]) && $this->obsoleteDefinitions[$id]->isSynchronized()) { $this->synchronize($id); } } /** * Removes a service definition. * * @param string $id The service identifier * * @api */ public function removeDefinition($id) { unset($this->definitions[strtolower($id)]); } /** * Returns true if the given service is defined. * * @param string $id The service identifier * * @return Boolean true if the service is defined, false otherwise * * @api */ public function has($id) { $id = strtolower($id); return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id); } /** * Gets a service. * * @param string $id The service identifier * @param integer $invalidBehavior The behavior when the service does not exist * * @return object The associated service * * @throws InvalidArgumentException when no definitions are available * @throws InactiveScopeException when the current scope is not active * @throws LogicException when a circular dependency is detected * @throws \Exception * * @see Reference * * @api */ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { $id = strtolower($id); try { return parent::get($id, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); } catch (InactiveScopeException $e) { if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return null; } throw $e; } catch (InvalidArgumentException $e) { if (isset($this->loading[$id])) { throw new LogicException(sprintf('The service "%s" has a circular reference to itself.', $id), 0, $e); } if (!$this->hasDefinition($id) && isset($this->aliasDefinitions[$id])) { return $this->get($this->aliasDefinitions[$id]); } try { $definition = $this->getDefinition($id); } catch (InvalidArgumentException $e) { if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return null; } throw $e; } $this->loading[$id] = true; try { $service = $this->createService($definition, $id); } catch (\Exception $e) { unset($this->loading[$id]); if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return null; } throw $e; } unset($this->loading[$id]); return $service; } } /** * Merges a ContainerBuilder with the current ContainerBuilder configuration. * * Service definitions overrides the current defined ones. * * But for parameters, they are overridden by the current ones. It allows * the parameters passed to the container constructor to have precedence * over the loaded ones. * * $container = new ContainerBuilder(array('foo' => 'bar')); * $loader = new LoaderXXX($container); * $loader->load('resource_name'); * $container->register('foo', new stdClass()); * * In the above example, even if the loaded resource defines a foo * parameter, the value will still be 'bar' as defined in the ContainerBuilder * constructor. * * @param ContainerBuilder $container The ContainerBuilder instance to merge. * * * @throws BadMethodCallException When this ContainerBuilder is frozen * * @api */ public function merge(ContainerBuilder $container) { if ($this->isFrozen()) { throw new BadMethodCallException('Cannot merge on a frozen container.'); } $this->addDefinitions($container->getDefinitions()); $this->addAliases($container->getAliases()); $this->getParameterBag()->add($container->getParameterBag()->all()); if ($this->trackResources) { foreach ($container->getResources() as $resource) { $this->addResource($resource); } } foreach ($this->extensions as $name => $extension) { if (!isset($this->extensionConfigs[$name])) { $this->extensionConfigs[$name] = array(); } $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name)); } } /** * Returns the configuration array for the given extension. * * @param string $name The name of the extension * * @return array An array of configuration * * @api */ public function getExtensionConfig($name) { if (!isset($this->extensionConfigs[$name])) { $this->extensionConfigs[$name] = array(); } return $this->extensionConfigs[$name]; } /** * Prepends a config array to the configs of the given extension. * * @param string $name The name of the extension * @param array $config The config to set */ public function prependExtensionConfig($name, array $config) { if (!isset($this->extensionConfigs[$name])) { $this->extensionConfigs[$name] = array(); } array_unshift($this->extensionConfigs[$name], $config); } /** * Compiles the container. * * This method passes the container to compiler * passes whose job is to manipulate and optimize * the container. * * The main compiler passes roughly do four things: * * * The extension configurations are merged; * * Parameter values are resolved; * * The parameter bag is frozen; * * Extension loading is disabled. * * @api */ public function compile() { $compiler = $this->getCompiler(); if ($this->trackResources) { foreach ($compiler->getPassConfig()->getPasses() as $pass) { $this->addObjectResource($pass); } } $compiler->compile($this); if ($this->trackResources) { foreach ($this->definitions as $definition) { if ($definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) { $this->addClassResource(new \ReflectionClass($class)); } } } $this->extensionConfigs = array(); parent::compile(); } /** * Gets all service ids. * * @return array An array of all defined service ids */ public function getServiceIds() { return array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds())); } /** * Adds the service aliases. * * @param array $aliases An array of aliases * * @api */ public function addAliases(array $aliases) { foreach ($aliases as $alias => $id) { $this->setAlias($alias, $id); } } /** * Sets the service aliases. * * @param array $aliases An array of aliases * * @api */ public function setAliases(array $aliases) { $this->aliasDefinitions = array(); $this->addAliases($aliases); } /** * Sets an alias for an existing service. * * @param string $alias The alias to create * @param string|Alias $id The service to alias * * @throws InvalidArgumentException if the id is not a string or an Alias * @throws InvalidArgumentException if the alias is for itself * * @api */ public function setAlias($alias, $id) { $alias = strtolower($alias); if (is_string($id)) { $id = new Alias($id); } elseif (!$id instanceof Alias) { throw new InvalidArgumentException('$id must be a string, or an Alias object.'); } if ($alias === strtolower($id)) { throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias)); } unset($this->definitions[$alias]); $this->aliasDefinitions[$alias] = $id; } /** * Removes an alias. * * @param string $alias The alias to remove * * @api */ public function removeAlias($alias) { unset($this->aliasDefinitions[strtolower($alias)]); } /** * Returns true if an alias exists under the given identifier. * * @param string $id The service identifier * * @return Boolean true if the alias exists, false otherwise * * @api */ public function hasAlias($id) { return isset($this->aliasDefinitions[strtolower($id)]); } /** * Gets all defined aliases. * * @return Alias[] An array of aliases * * @api */ public function getAliases() { return $this->aliasDefinitions; } /** * Gets an alias. * * @param string $id The service identifier * * @return Alias An Alias instance * * @throws InvalidArgumentException if the alias does not exist * * @api */ public function getAlias($id) { $id = strtolower($id); if (!$this->hasAlias($id)) { throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id)); } return $this->aliasDefinitions[$id]; } /** * Registers a service definition. * * This methods allows for simple registration of service definition * with a fluid interface. * * @param string $id The service identifier * @param string $class The service class * * @return Definition A Definition instance * * @api */ public function register($id, $class = null) { return $this->setDefinition(strtolower($id), new Definition($class)); } /** * Adds the service definitions. * * @param Definition[] $definitions An array of service definitions * * @api */ public function addDefinitions(array $definitions) { foreach ($definitions as $id => $definition) { $this->setDefinition($id, $definition); } } /** * Sets the service definitions. * * @param Definition[] $definitions An array of service definitions * * @api */ public function setDefinitions(array $definitions) { $this->definitions = array(); $this->addDefinitions($definitions); } /** * Gets all service definitions. * * @return Definition[] An array of Definition instances * * @api */ public function getDefinitions() { return $this->definitions; } /** * Sets a service definition. * * @param string $id The service identifier * @param Definition $definition A Definition instance * * @return Definition the service definition * * @throws BadMethodCallException When this ContainerBuilder is frozen * * @api */ public function setDefinition($id, Definition $definition) { if ($this->isFrozen()) { throw new BadMethodCallException('Adding definition to a frozen container is not allowed'); } $id = strtolower($id); unset($this->aliasDefinitions[$id]); return $this->definitions[$id] = $definition; } /** * Returns true if a service definition exists under the given identifier. * * @param string $id The service identifier * * @return Boolean true if the service definition exists, false otherwise * * @api */ public function hasDefinition($id) { return array_key_exists(strtolower($id), $this->definitions); } /** * Gets a service definition. * * @param string $id The service identifier * * @return Definition A Definition instance * * @throws InvalidArgumentException if the service definition does not exist * * @api */ public function getDefinition($id) { $id = strtolower($id); if (!$this->hasDefinition($id)) { throw new InvalidArgumentException(sprintf('The service definition "%s" does not exist.', $id)); } return $this->definitions[$id]; } /** * Gets a service definition by id or alias. * * The method "unaliases" recursively to return a Definition instance. * * @param string $id The service identifier or alias * * @return Definition A Definition instance * * @throws InvalidArgumentException if the service definition does not exist * * @api */ public function findDefinition($id) { while ($this->hasAlias($id)) { $id = (string) $this->getAlias($id); } return $this->getDefinition($id); } /** * Creates a service for a service definition. * * @param Definition $definition A service definition instance * @param string $id The service identifier * @param Boolean $tryProxy Whether to try proxying the service with a lazy proxy * * @return object The service described by the service definition * * @throws RuntimeException When the scope is inactive * @throws RuntimeException When the factory definition is incomplete * @throws RuntimeException When the service is a synthetic service * @throws InvalidArgumentException When configure callable is not callable * * @internal this method is public because of PHP 5.3 limitations, do not use it explicitly in your code */ public function createService(Definition $definition, $id, $tryProxy = true) { if ($definition->isSynthetic()) { throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id)); } if ($tryProxy && $definition->isLazy()) { $container = $this; $proxy = $this ->getProxyInstantiator() ->instantiateProxy( $container, $definition, $id, function () use ($definition, $id, $container) { return $container->createService($definition, $id, false); } ); $this->shareService($definition, $proxy, $id); return $proxy; } $parameterBag = $this->getParameterBag(); if (null !== $definition->getFile()) { require_once $parameterBag->resolveValue($definition->getFile()); } $arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments()))); if (null !== $definition->getFactoryMethod()) { if (null !== $definition->getFactoryClass()) { $factory = $parameterBag->resolveValue($definition->getFactoryClass()); } elseif (null !== $definition->getFactoryService()) { $factory = $this->get($parameterBag->resolveValue($definition->getFactoryService())); } else { throw new RuntimeException(sprintf('Cannot create service "%s" from factory method without a factory service or factory class.', $id)); } $service = call_user_func_array(array($factory, $definition->getFactoryMethod()), $arguments); } else { $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass())); $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); } if ($tryProxy || !$definition->isLazy()) { // share only if proxying failed, or if not a proxy $this->shareService($definition, $service, $id); } foreach ($definition->getMethodCalls() as $call) { $this->callMethod($service, $call); } $properties = $this->resolveServices($parameterBag->resolveValue($definition->getProperties())); foreach ($properties as $name => $value) { $service->$name = $value; } if ($callable = $definition->getConfigurator()) { if (is_array($callable)) { $callable[0] = $callable[0] instanceof Reference ? $this->get((string) $callable[0]) : $parameterBag->resolveValue($callable[0]); } if (!is_callable($callable)) { throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service))); } call_user_func($callable, $service); } return $service; } /** * Replaces service references by the real service instance and evaluates expressions. * * @param mixed $value A value * * @return mixed The same value with all service references replaced by * the real service instances and all expressions evaluated */ public function resolveServices($value) { if (is_array($value)) { foreach ($value as &$v) { $v = $this->resolveServices($v); } } elseif ($value instanceof Reference) { $value = $this->get((string) $value, $value->getInvalidBehavior()); } elseif ($value instanceof Definition) { $value = $this->createService($value, null); } elseif ($value instanceof Expression) { $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this)); } return $value; } /** * Returns service ids for a given tag. * * Example: * * $container->register('foo')->addTag('my.tag', array('hello' => 'world')); * * $serviceIds = $container->findTaggedServiceIds('my.tag'); * foreach ($serviceIds as $serviceId => $tags) { * foreach ($tags as $tag) { * echo $tag['hello']; * } * } * * @param string $name The tag name * * @return array An array of tags with the tagged service as key, holding a list of attribute arrays. * * @api */ public function findTaggedServiceIds($name) { $tags = array(); foreach ($this->getDefinitions() as $id => $definition) { if ($definition->hasTag($name)) { $tags[$id] = $definition->getTag($name); } } return $tags; } /** * Returns all tags the defined services use. * * @return array An array of tags */ public function findTags() { $tags = array(); foreach ($this->getDefinitions() as $id => $definition) { $tags = array_merge(array_keys($definition->getTags()), $tags); } return array_unique($tags); } /** * Returns the Service Conditionals. * * @param mixed $value An array of conditionals to return. * * @return array An array of Service conditionals */ public static function getServiceConditionals($value) { $services = array(); if (is_array($value)) { foreach ($value as $v) { $services = array_unique(array_merge($services, self::getServiceConditionals($v))); } } elseif ($value instanceof Reference && $value->getInvalidBehavior() === ContainerInterface::IGNORE_ON_INVALID_REFERENCE) { $services[] = (string) $value; } return $services; } /** * Retrieves the currently set proxy instantiator or instantiates one. * * @return InstantiatorInterface */ private function getProxyInstantiator() { if (!$this->proxyInstantiator) { $this->proxyInstantiator = new RealServiceInstantiator(); } return $this->proxyInstantiator; } /** * Synchronizes a service change. * * This method updates all services that depend on the given * service by calling all methods referencing it. * * @param string $id A service id */ private function synchronize($id) { foreach ($this->definitions as $definitionId => $definition) { // only check initialized services if (!$this->initialized($definitionId)) { continue; } foreach ($definition->getMethodCalls() as $call) { foreach ($call[1] as $argument) { if ($argument instanceof Reference && $id == (string) $argument) { $this->callMethod($this->get($definitionId), $call); } } } } } private function callMethod($service, $call) { $services = self::getServiceConditionals($call[1]); foreach ($services as $s) { if (!$this->has($s)) { return; } } call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1]))); } /** * Shares a given service in the container * * @param Definition $definition * @param mixed $service * @param string $id * * @throws InactiveScopeException */ private function shareService(Definition $definition, $service, $id) { if (self::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) { throw new InactiveScopeException($id, $scope); } $this->services[$lowerId = strtolower($id)] = $service; if (self::SCOPE_CONTAINER !== $scope) { $this->scopedServices[$scope][$lowerId] = $service; } } } private function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(); } return $this->expressionLanguage; } } PK]_J&DependencyInjection/ScopeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Scope Interface. * * @author Johannes M. Schmitt * * @api */ interface ScopeInterface { /** * @api */ public function getName(); /** * @api */ public function getParentName(); } PK] ]]"DependencyInjection/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * Tests if a given number belongs to a given math interval. * * An interval can represent a finite set of numbers: * * {1,2,3,4} * * An interval can represent numbers between two numbers: * * [1, +Inf] * ]-1,2[ * * The left delimiter can be [ (inclusive) or ] (exclusive). * The right delimiter can be [ (exclusive) or ] (inclusive). * Beside numbers, you can use -Inf and +Inf for the infinite. * * @author Fabien Potencier * * @see http://en.wikipedia.org/wiki/Interval_%28mathematics%29#The_ISO_notation */ class Interval { /** * Tests if the given number is in the math interval. * * @param integer $number A number * @param string $interval An interval * * @return Boolean * * @throws \InvalidArgumentException */ public static function test($number, $interval) { $interval = trim($interval); if (!preg_match('/^'.self::getIntervalRegexp().'$/x', $interval, $matches)) { throw new \InvalidArgumentException(sprintf('"%s" is not a valid interval.', $interval)); } if ($matches[1]) { foreach (explode(',', $matches[2]) as $n) { if ($number == $n) { return true; } } } else { $leftNumber = self::convertNumber($matches['left']); $rightNumber = self::convertNumber($matches['right']); return ('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber) && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber) ; } return false; } /** * Returns a Regexp that matches valid intervals. * * @return string A Regexp (without the delimiters) */ public static function getIntervalRegexp() { return <<[\[\]]) \s* (?P-Inf|\-?\d+(\.\d+)?) \s*,\s* (?P\+?Inf|\-?\d+(\.\d+)?) \s* (?P[\[\]]) EOF; } private static function convertNumber($number) { if ('-Inf' === $number) { return log(0); } elseif ('+Inf' === $number || 'Inf' === $number) { return -log(0); } return (float) $number; } } PK]P?}}(Translation/Writer/TranslationWriter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Writer; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Dumper\DumperInterface; /** * TranslationWriter writes translation messages. * * @author Michel Salib */ class TranslationWriter { /** * Dumpers used for export. * * @var array */ private $dumpers = array(); /** * Adds a dumper to the writer. * * @param string $format The format of the dumper * @param DumperInterface $dumper The dumper */ public function addDumper($format, DumperInterface $dumper) { $this->dumpers[$format] = $dumper; } /** * Obtains the list of supported formats. * * @return array */ public function getFormats() { return array_keys($this->dumpers); } /** * Writes translation from the catalogue according to the selected format. * * @param MessageCatalogue $catalogue The message catalogue to dump * @param string $format The format to use to dump the messages * @param array $options Options that are passed to the dumper * * @throws \InvalidArgumentException */ public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array()) { if (!isset($this->dumpers[$format])) { throw new \InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format)); } // get the right dumper $dumper = $this->dumpers[$format]; // save $dumper->dump($catalogue, $options); } } PK]66%Translation/Dumper/YamlFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Yaml\Yaml; /** * YamlFileDumper generates yaml files from a message catalogue. * * @author Michel Salib */ class YamlFileDumper extends FileDumper { /** * {@inheritDoc} */ protected function format(MessageCatalogue $messages, $domain) { return Yaml::dump($messages->all($domain)); } /** * {@inheritDoc} */ protected function getExtension() { return 'yml'; } } PK]oB$Translation/Dumper/CsvFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * CsvFileDumper generates a csv formatted string representation of a message catalogue. * * @author Stealth35 */ class CsvFileDumper extends FileDumper { private $delimiter = ';'; private $enclosure = '"'; /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $handle = fopen('php://memory', 'rb+'); foreach ($messages->all($domain) as $source => $target) { fputcsv($handle, array($source, $target), $this->delimiter, $this->enclosure); } rewind($handle); $output = stream_get_contents($handle); fclose($handle); return $output; } /** * Sets the delimiter and escape character for CSV. * * @param string $delimiter delimiter character * @param string $enclosure enclosure character */ public function setCsvControl($delimiter = ';', $enclosure = '"') { $this->delimiter = $delimiter; $this->enclosure = $enclosure; } /** * {@inheritDoc} */ protected function getExtension() { return 'csv'; } } PK]:$}}%Translation/Dumper/JsonFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; if (!defined('JSON_PRETTY_PRINT')) { define('JSON_PRETTY_PRINT', 128); } /** * JsonFileDumper generates an json formatted string representation of a message catalogue. * * @author singles */ class JsonFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { return json_encode($messages->all($domain), JSON_PRETTY_PRINT); } /** * {@inheritDoc} */ protected function getExtension() { return 'json'; } } PK]<̧&Translation/Dumper/XliffFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * XliffFileDumper generates xliff files from a message catalogue. * * @author Michel Salib */ class XliffFileDumper extends FileDumper { /** * {@inheritDoc} */ protected function format(MessageCatalogue $messages, $domain) { $dom = new \DOMDocument('1.0', 'utf-8'); $dom->formatOutput = true; $xliff = $dom->appendChild($dom->createElement('xliff')); $xliff->setAttribute('version', '1.2'); $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2'); $xliffFile = $xliff->appendChild($dom->createElement('file')); $xliffFile->setAttribute('source-language', $messages->getLocale()); $xliffFile->setAttribute('datatype', 'plaintext'); $xliffFile->setAttribute('original', 'file.ext'); $xliffBody = $xliffFile->appendChild($dom->createElement('body')); foreach ($messages->all($domain) as $source => $target) { $translation = $dom->createElement('trans-unit'); $translation->setAttribute('id', md5($source)); $translation->setAttribute('resname', $source); $s = $translation->appendChild($dom->createElement('source')); $s->appendChild($dom->createTextNode($source)); $t = $translation->appendChild($dom->createElement('target')); $t->appendChild($dom->createTextNode($target)); $xliffBody->appendChild($translation); } return $dom->saveXML(); } /** * {@inheritDoc} */ protected function getExtension() { return 'xlf'; } } PK]<**&Translation/Dumper/DumperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * DumperInterface is the interface implemented by all translation dumpers. * There is no common option. * * @author Michel Salib */ interface DumperInterface { /** * Dumps the message catalogue. * * @param MessageCatalogue $messages The message catalogue * @param array $options Options that are used by the dumper */ public function dump(MessageCatalogue $messages, $options = array()); } PK]%LL$Translation/Dumper/PhpFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * PhpFileDumper generates PHP files from a message catalogue. * * @author Michel Salib */ class PhpFileDumper extends FileDumper { /** * {@inheritDoc} */ protected function format(MessageCatalogue $messages, $domain) { $output = "all($domain), true).";\n"; return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'php'; } } PK]ਪ(#Translation/Dumper/PoFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * PoFileDumper generates a gettext formatted string representation of a message catalogue. * * @author Stealth35 */ class PoFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $output = 'msgid ""'."\n"; $output .= 'msgstr ""'."\n"; $output .= '"Content-Type: text/plain; charset=UTF-8\n"'."\n"; $output .= '"Content-Transfer-Encoding: 8bit\n"'."\n"; $output .= '"Language: '.$messages->getLocale().'\n"'."\n"; $output .= "\n"; $newLine = false; foreach ($messages->all($domain) as $source => $target) { if ($newLine) { $output .= "\n"; } else { $newLine = true; } $output .= sprintf('msgid "%s"'."\n", $this->escape($source)); $output .= sprintf('msgstr "%s"', $this->escape($target)); } return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'po'; } private function escape($str) { return addcslashes($str, "\0..\37\42\134"); } } PK]M 'Translation/Dumper/IcuResFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue. * * @author Stealth35 */ class IcuResFileDumper implements DumperInterface { /** * {@inheritDoc} */ public function dump(MessageCatalogue $messages, $options = array()) { if (!array_key_exists('path', $options)) { throw new \InvalidArgumentException('The file dumper need a path options.'); } // save a file for each domain foreach ($messages->getDomains() as $domain) { $file = $messages->getLocale().'.'.$this->getExtension(); $path = $options['path'].'/'.$domain.'/'; if (!file_exists($path)) { mkdir($path); } // backup if (file_exists($path.$file)) { copy($path.$file, $path.$file.'~'); } // save file file_put_contents($path.$file, $this->format($messages, $domain)); } } /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $data = $indexes = $resources = ''; foreach ($messages->all($domain) as $source => $target) { $indexes .= pack('v', strlen($data) + 28); $data .= $source."\0"; } $data .= $this->writePadding($data); $keyTop = $this->getPosition($data); foreach ($messages->all($domain) as $source => $target) { $resources .= pack('V', $this->getPosition($data)); $data .= pack('V', strlen($target)) .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8') .$this->writePadding($data) ; } $resOffset = $this->getPosition($data); $data .= pack('v', count($messages)) .$indexes .$this->writePadding($data) .$resources ; $bundleTop = $this->getPosition($data); $root = pack('V7', $resOffset + (2 << 28), // Resource Offset + Resource Type 6, // Index length $keyTop, // Index keys top $bundleTop, // Index resources top $bundleTop, // Index bundle top count($messages), // Index max table length 0 // Index attributes ); $header = pack('vC2v4C12@32', 32, // Header size 0xDA, 0x27, // Magic number 1 and 2 20, 0, 0, 2, // Rest of the header, ..., Size of a char 0x52, 0x65, 0x73, 0x42, // Data format identifier 1, 2, 0, 0, // Data version 1, 4, 0, 0 // Unicode version ); $output = $header .$root .$data; return $output; } private function writePadding($data) { $padding = strlen($data) % 4; if ($padding) { return str_repeat("\xAA", 4 - $padding); } } private function getPosition($data) { $position = (strlen($data) + 28) / 4; return $position; } /** * {@inheritDoc} */ protected function getExtension() { return 'res'; } } PK]A A #Translation/Dumper/MoFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Loader\MoFileLoader; /** * MoFileDumper generates a gettext formatted string representation of a message catalogue. * * @author Stealth35 */ class MoFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $output = $sources = $targets = $sourceOffsets = $targetOffsets = ''; $offsets = array(); $size = 0; foreach ($messages->all($domain) as $source => $target) { $offsets[] = array_map('strlen', array($sources, $source, $targets, $target)); $sources .= "\0".$source; $targets .= "\0".$target; ++$size; } $header = array( 'magicNumber' => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC, 'formatRevision' => 0, 'count' => $size, 'offsetId' => MoFileLoader::MO_HEADER_SIZE, 'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size), 'sizeHashes' => 0, 'offsetHashes' => MoFileLoader::MO_HEADER_SIZE + (16 * $size), ); $sourcesSize = strlen($sources); $sourcesStart = $header['offsetHashes'] + 1; foreach ($offsets as $offset) { $sourceOffsets .= $this->writeLong($offset[1]) .$this->writeLong($offset[0] + $sourcesStart); $targetOffsets .= $this->writeLong($offset[3]) .$this->writeLong($offset[2] + $sourcesStart + $sourcesSize); } $output = implode(array_map(array($this, 'writeLong'), $header)) .$sourceOffsets .$targetOffsets .$sources .$targets ; return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'mo'; } private function writeLong($str) { return pack('V*', $str); } } PK]&X$Translation/Dumper/IniFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * IniFileDumper generates an ini formatted string representation of a message catalogue. * * @author Stealth35 */ class IniFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $output = ''; foreach ($messages->all($domain) as $source => $target) { $escapeTarget = str_replace('"', '\"', $target); $output .= $source.'="'.$escapeTarget."\"\n"; } return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'ini'; } } PK]B^[[!Translation/Dumper/FileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s). * Performs backup of already existing files. * * Options: * - path (mandatory): the directory where the files should be saved * * @author Michel Salib */ abstract class FileDumper implements DumperInterface { /** * {@inheritDoc} */ public function dump(MessageCatalogue $messages, $options = array()) { if (!array_key_exists('path', $options)) { throw new \InvalidArgumentException('The file dumper needs a path option.'); } // save a file for each domain foreach ($messages->getDomains() as $domain) { $file = $domain.'.'.$messages->getLocale().'.'.$this->getExtension(); // backup $fullpath = $options['path'].'/'.$file; if (file_exists($fullpath)) { copy($fullpath, $fullpath.'~'); } // save file file_put_contents($fullpath, $this->format($messages, $domain)); } } /** * Transforms a domain of a message catalogue to its string representation. * * @param MessageCatalogue $messages * @param string $domain * * @return string representation */ abstract protected function format(MessageCatalogue $messages, $domain); /** * Gets the file extension of the dumper. * * @return string file extension */ abstract protected function getExtension(); } PK]>{GG#Translation/Dumper/QtFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * QtFileDumper generates ts files from a message catalogue. * * @author Benjamin Eberlei */ class QtFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain) { $dom = new \DOMDocument('1.0', 'utf-8'); $dom->formatOutput = true; $ts = $dom->appendChild($dom->createElement('TS')); $context = $ts->appendChild($dom->createElement('context')); $context->appendChild($dom->createElement('name', $domain)); foreach ($messages->all($domain) as $source => $target) { $message = $context->appendChild($dom->createElement('message')); $message->appendChild($dom->createElement('source', $source)); $message->appendChild($dom->createElement('translation', $target)); } return $dom->saveXML(); } /** * {@inheritDoc} */ protected function getExtension() { return 'ts'; } } PK]b*0oo"Translation/PluralizationRules.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * Returns the plural rules for a given locale. * * @author Fabien Potencier */ class PluralizationRules { // @codeCoverageIgnoreStart private static $rules = array(); /** * Returns the plural position to use for the given locale and number. * * @param integer $number The number * @param string $locale The locale * * @return integer The plural position */ public static function get($number, $locale) { if ('pt_BR' === $locale) { // temporary set a locale for brazilian $locale = 'xbr'; } if (strlen($locale) > 3) { $locale = substr($locale, 0, -strlen(strrchr($locale, '_'))); } if (isset(self::$rules[$locale])) { $return = call_user_func(self::$rules[$locale], $number); if (!is_int($return) || $return < 0) { return 0; } return $return; } /* * The plural rules are derived from code of the Zend Framework (2010-09-25), * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd). * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) */ switch ($locale) { case 'bo': case 'dz': case 'id': case 'ja': case 'jv': case 'ka': case 'km': case 'kn': case 'ko': case 'ms': case 'th': case 'tr': case 'vi': case 'zh': return 0; break; case 'af': case 'az': case 'bn': case 'bg': case 'ca': case 'da': case 'de': case 'el': case 'en': case 'eo': case 'es': case 'et': case 'eu': case 'fa': case 'fi': case 'fo': case 'fur': case 'fy': case 'gl': case 'gu': case 'ha': case 'he': case 'hu': case 'is': case 'it': case 'ku': case 'lb': case 'ml': case 'mn': case 'mr': case 'nah': case 'nb': case 'ne': case 'nl': case 'nn': case 'no': case 'om': case 'or': case 'pa': case 'pap': case 'ps': case 'pt': case 'so': case 'sq': case 'sv': case 'sw': case 'ta': case 'te': case 'tk': case 'ur': case 'zu': return ($number == 1) ? 0 : 1; case 'am': case 'bh': case 'fil': case 'fr': case 'gun': case 'hi': case 'ln': case 'mg': case 'nso': case 'xbr': case 'ti': case 'wa': return (($number == 0) || ($number == 1)) ? 0 : 1; case 'be': case 'bs': case 'hr': case 'ru': case 'sr': case 'uk': return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'cs': case 'sk': return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); case 'ga': return ($number == 1) ? 0 : (($number == 2) ? 1 : 2); case 'lt': return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'sl': return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3)); case 'mk': return ($number % 10 == 1) ? 0 : 1; case 'mt': return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); case 'lv': return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2); case 'pl': return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); case 'cy': return ($number == 1) ? 0 : (($number == 2) ? 1 : ((($number == 8) || ($number == 11)) ? 2 : 3)); case 'ro': return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); case 'ar': return ($number == 0) ? 0 : (($number == 1) ? 1 : (($number == 2) ? 2 : ((($number >= 3) && ($number <= 10)) ? 3 : ((($number >= 11) && ($number <= 99)) ? 4 : 5)))); default: return 0; } } /** * Overrides the default plural rule for a given locale. * * @param string $rule A PHP callable * @param string $locale The locale * * @throws \LogicException */ public static function set($rule, $locale) { if ('pt_BR' === $locale) { // temporary set a locale for brazilian $locale = 'xbr'; } if (strlen($locale) > 3) { $locale = substr($locale, 0, -strlen(strrchr($locale, '_'))); } if (!is_callable($rule)) { throw new \LogicException('The given rule can not be called'); } self::$rules[$locale] = $rule; } // @codeCoverageIgnoreEnd } PK]N@ $Translation/Loader/IniFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * IniFileLoader loads translations from an ini file. * * @author stealth35 */ class IniFileLoader extends ArrayLoader implements LoaderInterface { /** * {@inheritdoc} */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = parse_ini_file($resource, true); $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } } PK])-d+ #Translation/Loader/QtFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * QtFileLoader loads translations from QT Translations XML files. * * @author Benjamin Eberlei * * @api */ class QtFileLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } try { $dom = XmlUtils::loadFile($resource); } catch (\InvalidArgumentException $e) { throw new InvalidResourceException(sprintf('Unable to load "%s".', $resource), $e->getCode(), $e); } $internalErrors = libxml_use_internal_errors(true); libxml_clear_errors(); $xpath = new \DOMXPath($dom); $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]'); $catalogue = new MessageCatalogue($locale); if ($nodes->length == 1) { $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message'); foreach ($translations as $translation) { $translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue; if (!empty($translationValue)) { $catalogue->set( (string) $translation->getElementsByTagName('source')->item(0)->nodeValue, $translationValue, $domain ); } $translation = $translation->nextSibling; } $catalogue->addResource(new FileResource($resource)); } libxml_use_internal_errors($internalErrors); return $catalogue; } } PK]:%Translation/Loader/YamlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\Yaml\Exception\ParseException; /** * YamlFileLoader loads translations from Yaml files. * * @author Fabien Potencier * * @api */ class YamlFileLoader extends ArrayLoader implements LoaderInterface { private $yamlParser; /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } try { $messages = $this->yamlParser->parse(file_get_contents($resource)); } catch (ParseException $e) { throw new InvalidResourceException('Error parsing YAML.', 0, $e); } // empty file if (null === $messages) { $messages = array(); } // not an array if (!is_array($messages)) { throw new InvalidResourceException(sprintf('The file "%s" must contain a YAML array.', $resource)); } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } } PK]v#Translation/Loader/MoFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/) */ class MoFileLoader extends ArrayLoader implements LoaderInterface { /** * Magic used for validating the format of a MO file as well as * detecting if the machine used to create that file was little endian. * * @var float */ const MO_LITTLE_ENDIAN_MAGIC = 0x950412de; /** * Magic used for validating the format of a MO file as well as * detecting if the machine used to create that file was big endian. * * @var float */ const MO_BIG_ENDIAN_MAGIC = 0xde120495; /** * The size of the header of a MO file in bytes. * * @var integer Number of bytes. */ const MO_HEADER_SIZE = 28; public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = $this->parse($resource); // empty file if (null === $messages) { $messages = array(); } // not an array if (!is_array($messages)) { throw new InvalidResourceException(sprintf('The file "%s" must contain a valid mo file.', $resource)); } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Parses machine object (MO) format, independent of the machine's endian it * was created on. Both 32bit and 64bit systems are supported. * * @param resource $resource * * @return array * @throws InvalidResourceException If stream content has an invalid format. */ private function parse($resource) { $stream = fopen($resource, 'r'); $stat = fstat($stream); if ($stat['size'] < self::MO_HEADER_SIZE) { throw new InvalidResourceException("MO stream content has an invalid format."); } $magic = unpack('V1', fread($stream, 4)); $magic = hexdec(substr(dechex(current($magic)), -8)); if ($magic == self::MO_LITTLE_ENDIAN_MAGIC) { $isBigEndian = false; } elseif ($magic == self::MO_BIG_ENDIAN_MAGIC) { $isBigEndian = true; } else { throw new InvalidResourceException("MO stream content has an invalid format."); } // formatRevision $this->readLong($stream, $isBigEndian); $count = $this->readLong($stream, $isBigEndian); $offsetId = $this->readLong($stream, $isBigEndian); $offsetTranslated = $this->readLong($stream, $isBigEndian); // sizeHashes $this->readLong($stream, $isBigEndian); // offsetHashes $this->readLong($stream, $isBigEndian); $messages = array(); for ($i = 0; $i < $count; $i++) { $singularId = $pluralId = null; $translated = null; fseek($stream, $offsetId + $i * 8); $length = $this->readLong($stream, $isBigEndian); $offset = $this->readLong($stream, $isBigEndian); if ($length < 1) { continue; } fseek($stream, $offset); $singularId = fread($stream, $length); if (strpos($singularId, "\000") !== false) { list($singularId, $pluralId) = explode("\000", $singularId); } fseek($stream, $offsetTranslated + $i * 8); $length = $this->readLong($stream, $isBigEndian); $offset = $this->readLong($stream, $isBigEndian); fseek($stream, $offset); $translated = fread($stream, $length); if (strpos($translated, "\000") !== false) { $translated = explode("\000", $translated); } $ids = array('singular' => $singularId, 'plural' => $pluralId); $item = compact('ids', 'translated'); if (is_array($item['translated'])) { $messages[$item['ids']['singular']] = stripcslashes($item['translated'][0]); if (isset($item['ids']['plural'])) { $plurals = array(); foreach ($item['translated'] as $plural => $translated) { $plurals[] = sprintf('{%d} %s', $plural, $translated); } $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals)); } } elseif (!empty($item['ids']['singular'])) { $messages[$item['ids']['singular']] = stripcslashes($item['translated']); } } fclose($stream); return array_filter($messages); } /** * Reads an unsigned long from stream respecting endianess. * * @param resource $stream * @param boolean $isBigEndian * @return integer */ private function readLong($stream, $isBigEndian) { $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4)); $result = current($result); return (integer) substr($result, -8); } } PK]: Z""0Translation/Loader/schema/dic/xliff-core/xml.xsdnu[

About the XML namespace

This schema document describes the XML namespace, in a form suitable for import by other schema documents.

See http://www.w3.org/XML/1998/namespace.html and http://www.w3.org/TR/REC-xml for information about this namespace.

Note that local names in this namespace are intended to be defined only by the World Wide Web Consortium or its subgroups. The names currently defined in this namespace are listed below. They should not be used with conflicting semantics by any Working Group, specification, or document instance.

See further below in this document for more information about how to refer to this schema document from your own XSD schema documents and about the namespace-versioning policy governing this schema document.

lang (as an attribute name)

denotes an attribute whose value is a language code for the natural language of the content of any element; its value is inherited. This name is reserved by virtue of its definition in the XML specification.

Notes

Attempting to install the relevant ISO 2- and 3-letter codes as the enumerated possible values is probably never going to be a realistic possibility.

See BCP 47 at http://www.rfc-editor.org/rfc/bcp/bcp47.txt and the IANA language subtag registry at http://www.iana.org/assignments/language-subtag-registry for further information.

The union allows for the 'un-declaration' of xml:lang with the empty string.

space (as an attribute name)

denotes an attribute whose value is a keyword indicating what whitespace processing discipline is intended for the content of the element; its value is inherited. This name is reserved by virtue of its definition in the XML specification.

base (as an attribute name)

denotes an attribute whose value provides a URI to be used as the base for interpreting any relative URIs in the scope of the element on which it appears; its value is inherited. This name is reserved by virtue of its definition in the XML Base specification.

See http://www.w3.org/TR/xmlbase/ for information about this attribute.

id (as an attribute name)

denotes an attribute whose value should be interpreted as if declared to be of type ID. This name is reserved by virtue of its definition in the xml:id specification.

See http://www.w3.org/TR/xml-id/ for information about this attribute.

Father (in any context at all)

denotes Jon Bosak, the chair of the original XML Working Group. This name is reserved by the following decision of the W3C XML Plenary and XML Coordination groups:

In appreciation for his vision, leadership and dedication the W3C XML Plenary on this 10th day of February, 2000, reserves for Jon Bosak in perpetuity the XML name "xml:Father".

About this schema document

This schema defines attributes and an attribute group suitable for use by schemas wishing to allow xml:base, xml:lang, xml:space or xml:id attributes on elements they define.

To enable this, such a schema must import this schema for the XML namespace, e.g. as follows:

          <schema.. .>
          .. .
           <import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
     

or


           <import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
     

Subsequently, qualified reference to any of the attributes or the group defined below will have the desired effect, e.g.

          <type.. .>
          .. .
           <attributeGroup ref="xml:specialAttrs"/>
     

will define a type which will schema-validate an instance element with any of those attributes.

Versioning policy for this schema document

In keeping with the XML Schema WG's standard versioning policy, this schema document will persist at http://www.w3.org/2009/01/xml.xsd.

At the date of issue it can also be found at http://www.w3.org/2001/xml.xsd.

The schema document at that URI may however change in the future, in order to remain compatible with the latest version of XML Schema itself, or with the XML namespace itself. In other words, if the XML Schema or XML namespaces change, the version of this document at http://www.w3.org/2001/xml.xsd will change accordingly; the version at http://www.w3.org/2009/01/xml.xsd will not change.

Previous dated (and unchanging) versions of this schema document are at:

PK]xOBTranslation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu[ Values for the attribute 'context-type'. Indicates a database content. Indicates the content of an element within an XML document. Indicates the name of an element within an XML document. Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found. Indicates a the number of parameters contained within the <source>. Indicates notes pertaining to the parameters in the <source>. Indicates the content of a record within a database. Indicates the name of a record within a database. Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file. Values for the attribute 'count-type'. Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts. Indicates the count units are translation units existing already in the same document. Indicates a total count. Values for the attribute 'ctype' when used other elements than <ph> or <x>. Indicates a run of bolded text. Indicates a run of text in italics. Indicates a run of underlined text. Indicates a run of hyper-text. Values for the attribute 'ctype' when used with <ph> or <x>. Indicates a inline image. Indicates a page break. Indicates a line break. Values for the attribute 'datatype'. Indicates Active Server Page data. Indicates C source file data. Indicates Channel Definition Format (CDF) data. Indicates ColdFusion data. Indicates C++ source file data. Indicates C-Sharp data. Indicates strings from C, ASM, and driver files data. Indicates comma-separated values data. Indicates database data. Indicates portions of document that follows data and contains metadata. Indicates portions of document that precedes data and contains metadata. Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import). Indicates standard user input screen data. Indicates HyperText Markup Language (HTML) data - document instance. Indicates content within an HTML document’s <body> element. Indicates Windows INI file data. Indicates Interleaf data. Indicates Java source file data (extension '.java'). Indicates Java property resource bundle data. Indicates Java list resource bundle data. Indicates JavaScript source file data. Indicates JScript source file data. Indicates information relating to formatting. Indicates LISP source file data. Indicates information relating to margin formats. Indicates a file containing menu. Indicates numerically identified string table. Indicates Maker Interchange Format (MIF) data. Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute. Indicates GNU Machine Object data. Indicates Message Librarian strings created by Novell's Message Librarian Tool. Indicates information to be displayed at the bottom of each page of a document. Indicates information to be displayed at the top of each page of a document. Indicates a list of property values (e.g., settings within INI files or preferences dialog). Indicates Pascal source file data. Indicates Hypertext Preprocessor data. Indicates plain text file (no formatting other than, possibly, wrapping). Indicates GNU Portable Object file. Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc. Indicates Windows .NET binary resources. Indicates Windows .NET Resources. Indicates Rich Text Format (RTF) data. Indicates Standard Generalized Markup Language (SGML) data - document instance. Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD). Indicates Scalable Vector Graphic (SVG) data. Indicates VisualBasic Script source file. Indicates warning message. Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file). Indicates Extensible HyperText Markup Language (XHTML) data - document instance. Indicates Extensible Markup Language (XML) data - document instance. Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD). Indicates Extensible Stylesheet Language (XSL) data. Indicates XUL elements. Values for the attribute 'mtype'. Indicates the marked text is an abbreviation. ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept. ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective'). ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging'). ISO-12620: A proper-name term, such as the name of an agency or other proper entity. ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another. ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language. Indicates the marked text is a date and/or time. ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign. ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form. ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula. ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record. ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy'). ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body. ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages. ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like. ISO-12620 2.1.17: A unit to track object. Indicates the marked text is a name. ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others. ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system. Indicates the marked text is a phrase. ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase. Indicates the marked text should not be translated. ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet. Indicates that the marked text represents a segment. ISO-12620 2.1.18.2: A fixed, lexicalized phrase. ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs'). ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system. ISO-12620 2.1.19: A fixed chunk of recurring text. ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof. ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry. ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language. Indicates the marked text is a term. ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted. ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system. ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza'). ISO-12620 2.1.9: One of the alternate forms of a term. Values for the attribute 'restype'. Indicates a Windows RC AUTO3STATE control. Indicates a Windows RC AUTOCHECKBOX control. Indicates a Windows RC AUTORADIOBUTTON control. Indicates a Windows RC BEDIT control. Indicates a bitmap, for example a BITMAP resource in Windows. Indicates a button object, for example a BUTTON control Windows. Indicates a caption, such as the caption of a dialog box. Indicates the cell in a table, for example the content of the <td> element in HTML. Indicates check box object, for example a CHECKBOX control in Windows. Indicates a menu item with an associated checkbox. Indicates a list box, but with a check-box for each item. Indicates a color selection dialog. Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows. Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234). Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403). Indicates a UI base class element that cannot be represented by any other element. Indicates a context menu. Indicates a Windows RC CTEXT control. Indicates a cursor, for example a CURSOR resource in Windows. Indicates a date/time picker. Indicates a Windows RC DEFPUSHBUTTON control. Indicates a dialog box. Indicates a Windows RC DLGINIT resource block. Indicates an edit box object, for example an EDIT control in Windows. Indicates a filename. Indicates a file dialog. Indicates a footnote. Indicates a font name. Indicates a footer. Indicates a frame object. Indicates a XUL grid element. Indicates a groupbox object, for example a GROUPBOX control in Windows. Indicates a header item. Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML. Indicates a Windows RC HEDIT control. Indicates a horizontal scrollbar. Indicates an icon, for example an ICON resource in Windows. Indicates a Windows RC IEDIT control. Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF. Indicates a label object. Indicates a label that is also a HTML link (not necessarily a URL). Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML). Indicates a listbox object, for example an LISTBOX control in Windows. Indicates an list item (an entry in a list). Indicates a Windows RC LTEXT control. Indicates a menu (a group of menu-items). Indicates a toolbar containing one or more tope level menus. Indicates a menu item (an entry in a menu). Indicates a XUL menuseparator element. Indicates a message, for example an entry in a MESSAGETABLE resource in Windows. Indicates a calendar control. Indicates an edit box beside a spin control. Indicates a catch all for rectangular areas. Indicates a standalone menu not necessarily associated with a menubar. Indicates a pushbox object, for example a PUSHBOX control in Windows. Indicates a Windows RC PUSHBUTTON control. Indicates a radio button object. Indicates a menuitem with associated radio button. Indicates raw data resources for an application. Indicates a row in a table. Indicates a Windows RC RTEXT control. Indicates a user navigable container used to show a portion of a document. Indicates a generic divider object (e.g. menu group separator). Windows accelerators, shortcuts in resource or property files. Indicates a UI control to indicate process activity but not progress. Indicates a splitter bar. Indicates a Windows RC STATE3 control. Indicates a window for providing feedback to the users, like 'read-only', etc. Indicates a string, for example an entry in a STRINGTABLE resource in Windows. Indicates a layers of controls with a tab to select layers. Indicates a display and edits regular two-dimensional tables of cells. Indicates a XUL textbox element. Indicates a UI button that can be toggled to on or off state. Indicates an array of controls, usually buttons. Indicates a pop up tool tip text. Indicates a bar with a pointer indicating a position within a certain range. Indicates a control that displays a set of hierarchical data. Indicates a URI (URN or URL). Indicates a Windows RC USERBUTTON control. Indicates a user-defined control like CONTROL control in Windows. Indicates the text of a variable. Indicates version information about a resource like VERSIONINFO in Windows. Indicates a vertical scrollbar. Indicates a graphical window. Values for the attribute 'size-unit'. Indicates a size in 8-bit bytes. Indicates a size in Unicode characters. Indicates a size in columns. Used for HTML text area. Indicates a size in centimeters. Indicates a size in dialog units, as defined in Windows resources. Indicates a size in 'font-size' units (as defined in CSS). Indicates a size in 'x-height' units (as defined in CSS). Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster' Indicates a size in inches. Indicates a size in millimeters. Indicates a size in percentage. Indicates a size in pixels. Indicates a size in point. Indicates a size in rows. Used for HTML text area. Values for the attribute 'state'. Indicates the terminating state. Indicates only non-textual information needs adaptation. Indicates both text and non-textual information needs adaptation. Indicates only non-textual information needs review. Indicates both text and non-textual information needs review. Indicates that only the text of the item needs to be reviewed. Indicates that the item needs to be translated. Indicates that the item is new. For example, translation units that were not in a previous version of the document. Indicates that changes are reviewed and approved. Indicates that the item has been translated. Values for the attribute 'state-qualifier'. Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously. Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.). Indicates a match based on matching IDs (in addition to matching text). Indicates a translation derived from a glossary. Indicates a translation derived from existing translation. Indicates a translation derived from machine translation. Indicates a translation derived from a translation repository. Indicates a translation derived from a translation memory. Indicates the translation is suggested by machine translation. Indicates that the item has been rejected because of incorrect grammar. Indicates that the item has been rejected because it is incorrect. Indicates that the item has been rejected because it is too long or too short. Indicates that the item has been rejected because of incorrect spelling. Indicates the translation is suggested by translation memory. Values for the attribute 'unit'. Refers to words. Refers to pages. Refers to <trans-unit> elements. Refers to <bin-unit> elements. Refers to glyphs. Refers to <trans-unit> and/or <bin-unit> elements. Refers to the occurrences of instances defined by the count-type value. Refers to characters. Refers to lines. Refers to sentences. Refers to paragraphs. Refers to segments. Refers to placeables (inline elements). Values for the attribute 'priority'. Highest priority. High priority. High priority, but not as important as 2. High priority, but not as important as 3. Medium priority, but more important than 6. Medium priority, but less important than 5. Low priority, but more important than 8. Low priority, but more important than 9. Low priority. Lowest priority. This value indicates that all properties can be reformatted. This value must be used alone. This value indicates that no properties should be reformatted. This value must be used alone. This value indicates that all information in the coord attribute can be modified. This value indicates that the x information in the coord attribute can be modified. This value indicates that the y information in the coord attribute can be modified. This value indicates that the cx information in the coord attribute can be modified. This value indicates that the cy information in the coord attribute can be modified. This value indicates that all the information in the font attribute can be modified. This value indicates that the name information in the font attribute can be modified. This value indicates that the size information in the font attribute can be modified. This value indicates that the weight information in the font attribute can be modified. This value indicates that the information in the css-style attribute can be modified. This value indicates that the information in the style attribute can be modified. This value indicates that the information in the exstyle attribute can be modified. Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document. Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed. Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed. Represents a translation proposal from a translation memory or other resource. Represents a previous version of the target element. Represents a rejected version of the target element. Represents a translation to be used for reference purposes only, for example from a related product or a different language. Represents a proposed translation that was used for the translation of the trans-unit, possibly modified. Values for the attribute 'coord'. Version values: 1.0 and 1.1 are allowed for backward compatibility. PK]'su u %Translation/Loader/JsonFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * JsonFileLoader loads translations from an json file. * * @author singles */ class JsonFileLoader extends ArrayLoader implements LoaderInterface { /** * {@inheritdoc} */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = json_decode(file_get_contents($resource), true); if (0 < $errorCode = json_last_error()) { throw new InvalidResourceException(sprintf('Error parsing JSON - %s', $this->getJSONErrorMessage($errorCode))); } if (null === $messages) { $messages = array(); } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Translates JSON_ERROR_* constant into meaningful message. * * @param integer $errorCode Error code returned by json_last_error() call * * @return string Message string */ private function getJSONErrorMessage($errorCode) { switch ($errorCode) { case JSON_ERROR_DEPTH: return 'Maximum stack depth exceeded'; case JSON_ERROR_STATE_MISMATCH: return 'Underflow or the modes mismatch'; case JSON_ERROR_CTRL_CHAR: return 'Unexpected control character found'; case JSON_ERROR_SYNTAX: return 'Syntax error, malformed JSON'; case JSON_ERROR_UTF8: return 'Malformed UTF-8 characters, possibly incorrectly encoded'; default: return 'Unknown error'; } } } PK]TÏ'Translation/Loader/IcuDatFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * IcuResFileLoader loads translations from a resource bundle. * * @author stealth35 */ class IcuDatFileLoader extends IcuResFileLoader { /** * {@inheritdoc} */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource.'.dat')) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource.'.dat')) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $rb = new \ResourceBundle($locale, $resource); if (!$rb) { throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource)); } elseif (intl_is_failure($rb->getErrorCode())) { throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode()); } $messages = $this->flatten($rb); $catalogue = new MessageCatalogue($locale); $catalogue->add($messages, $domain); $catalogue->addResource(new FileResource($resource.'.dat')); return $catalogue; } } PK]CSz z 'Translation/Loader/IcuResFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\DirectoryResource; /** * IcuResFileLoader loads translations from a resource bundle. * * @author stealth35 */ class IcuResFileLoader implements LoaderInterface { /** * {@inheritdoc} */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!is_dir($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $rb = new \ResourceBundle($locale, $resource); if (!$rb) { throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource)); } elseif (intl_is_failure($rb->getErrorCode())) { throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode()); } $messages = $this->flatten($rb); $catalogue = new MessageCatalogue($locale); $catalogue->add($messages, $domain); $catalogue->addResource(new DirectoryResource($resource)); return $catalogue; } /** * Flattens an ResourceBundle * * The scheme used is: * key { key2 { key3 { "value" } } } * Becomes: * 'key.key2.key3' => 'value' * * This function takes an array by reference and will modify it * * @param \ResourceBundle $rb the ResourceBundle that will be flattened * @param array $messages used internally for recursive calls * @param string $path current path being parsed, used internally for recursive calls * * @return array the flattened ResourceBundle */ protected function flatten(\ResourceBundle $rb, array &$messages = array(), $path = null) { foreach ($rb as $key => $value) { $nodePath = $path ? $path.'.'.$key : $key; if ($value instanceof \ResourceBundle) { $this->flatten($value, $messages, $nodePath); } else { $messages[$nodePath] = $value; } } return $messages; } } PK]l#tt&Translation/Loader/LoaderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; /** * LoaderInterface is the interface implemented by all translation loaders. * * @author Fabien Potencier * * @api */ interface LoaderInterface { /** * Loads a locale. * * @param mixed $resource A resource * @param string $locale A locale * @param string $domain The domain * * @return MessageCatalogue A MessageCatalogue instance * * @api * * @throws NotFoundResourceException when the resource cannot be found * @throws InvalidResourceException when the resource cannot be loaded */ public function load($resource, $locale, $domain = 'messages'); } PK]r;;$Translation/Loader/PhpFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * PhpFileLoader loads translations from PHP files returning an array of translations. * * @author Fabien Potencier * * @api */ class PhpFileLoader extends ArrayLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = require($resource); $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } } PK]R"Translation/Loader/ArrayLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; /** * ArrayLoader loads translations from a PHP array. * * @author Fabien Potencier * * @api */ class ArrayLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { $this->flatten($resource); $catalogue = new MessageCatalogue($locale); $catalogue->add($resource, $domain); return $catalogue; } /** * Flattens an nested array of translations * * The scheme used is: * 'key' => array('key2' => array('key3' => 'value')) * Becomes: * 'key.key2.key3' => 'value' * * This function takes an array by reference and will modify it * * @param array &$messages The array that will be flattened * @param array $subnode Current subnode being parsed, used internally for recursive calls * @param string $path Current path being parsed, used internally for recursive calls */ private function flatten(array &$messages, array $subnode = null, $path = null) { if (null === $subnode) { $subnode =& $messages; } foreach ($subnode as $key => $value) { if (is_array($value)) { $nodePath = $path ? $path.'.'.$key : $key; $this->flatten($messages, $value, $nodePath); if (null === $path) { unset($messages[$key]); } } elseif (null !== $path) { $messages[$path.'.'.$key] = $value; } } } } PK]*#Translation/Loader/PoFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/) * @copyright Copyright (c) 2012, Clemens Tolboom */ class PoFileLoader extends ArrayLoader implements LoaderInterface { public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = $this->parse($resource); // empty file if (null === $messages) { $messages = array(); } // not an array if (!is_array($messages)) { throw new InvalidResourceException(sprintf('The file "%s" must contain a valid po file.', $resource)); } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Parses portable object (PO) format. * * From http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files * we should be able to parse files having: * * white-space * # translator-comments * #. extracted-comments * #: reference... * #, flag... * #| msgid previous-untranslated-string * msgid untranslated-string * msgstr translated-string * * extra or different lines are: * * #| msgctxt previous-context * #| msgid previous-untranslated-string * msgctxt context * * #| msgid previous-untranslated-string-singular * #| msgid_plural previous-untranslated-string-plural * msgid untranslated-string-singular * msgid_plural untranslated-string-plural * msgstr[0] translated-string-case-0 * ... * msgstr[N] translated-string-case-n * * The definition states: * - white-space and comments are optional. * - msgid "" that an empty singleline defines a header. * * This parser sacrifices some features of the reference implementation the * differences to that implementation are as follows. * - No support for comments spanning multiple lines. * - Translator and extracted comments are treated as being the same type. * - Message IDs are allowed to have other encodings as just US-ASCII. * * Items with an empty id are ignored. * * @param resource $resource * * @return array */ private function parse($resource) { $stream = fopen($resource, 'r'); $defaults = array( 'ids' => array(), 'translated' => null, ); $messages = array(); $item = $defaults; while ($line = fgets($stream)) { $line = trim($line); if ($line === '') { // Whitespace indicated current item is done $this->addMessage($messages, $item); $item = $defaults; } elseif (substr($line, 0, 7) === 'msgid "') { // We start a new msg so save previous // TODO: this fails when comments or contexts are added $this->addMessage($messages, $item); $item = $defaults; $item['ids']['singular'] = substr($line, 7, -1); } elseif (substr($line, 0, 8) === 'msgstr "') { $item['translated'] = substr($line, 8, -1); } elseif ($line[0] === '"') { $continues = isset($item['translated']) ? 'translated' : 'ids'; if (is_array($item[$continues])) { end($item[$continues]); $item[$continues][key($item[$continues])] .= substr($line, 1, -1); } else { $item[$continues] .= substr($line, 1, -1); } } elseif (substr($line, 0, 14) === 'msgid_plural "') { $item['ids']['plural'] = substr($line, 14, -1); } elseif (substr($line, 0, 7) === 'msgstr[') { $size = strpos($line, ']'); $item['translated'][(integer) substr($line, 7, 1)] = substr($line, $size + 3, -1); } } // save last item $this->addMessage($messages, $item); fclose($stream); return $messages; } /** * Save a translation item to the messages. * * A .po file could contain by error missing plural indexes. We need to * fix these before saving them. * * @param array $messages * @param array $item */ private function addMessage(array &$messages, array $item) { if (is_array($item['translated'])) { $messages[$item['ids']['singular']] = stripslashes($item['translated'][0]); if (isset($item['ids']['plural'])) { $plurals = $item['translated']; // PO are by definition indexed so sort by index. ksort($plurals); // Make sure every index is filled. end($plurals); $count = key($plurals); // Fill missing spots with '-'. $empties = array_fill(0, $count+1, '-'); $plurals += $empties; ksort($plurals); $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals)); } } elseif (!empty($item['ids']['singular'])) { $messages[$item['ids']['singular']] = stripslashes($item['translated']); } } } PK]i3" " $Translation/Loader/CsvFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * CsvFileLoader loads translations from CSV files. * * @author Saša Stamenković * * @api */ class CsvFileLoader extends ArrayLoader implements LoaderInterface { private $delimiter = ';'; private $enclosure = '"'; private $escape = '\\'; /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = array(); try { $file = new \SplFileObject($resource, 'rb'); } catch (\RuntimeException $e) { throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e); } $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY); $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape); foreach ($file as $data) { if (substr($data[0], 0, 1) === '#') { continue; } if (!isset($data[1])) { continue; } if (count($data) == 2) { $messages[$data[0]] = $data[1]; } else { continue; } } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Sets the delimiter, enclosure, and escape character for CSV. * * @param string $delimiter delimiter character * @param string $enclosure enclosure character * @param string $escape escape character */ public function setCsvControl($delimiter = ';', $enclosure = '"', $escape = '\\') { $this->delimiter = $delimiter; $this->enclosure = $enclosure; $this->escape = $escape; } } PK]_BB&Translation/Loader/XliffFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * XliffFileLoader loads translations from XLIFF files. * * @author Fabien Potencier * * @api */ class XliffFileLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } list($xml, $encoding) = $this->parseFile($resource); $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2'); $catalogue = new MessageCatalogue($locale); foreach ($xml->xpath('//xliff:trans-unit') as $translation) { $attributes = $translation->attributes(); if (!(isset($attributes['resname']) || isset($translation->source)) || !isset($translation->target)) { continue; } $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source; $target = (string) $translation->target; // If the xlf file has another encoding specified, try to convert it because // simple_xml will always return utf-8 encoded values if ('UTF-8' !== $encoding && !empty($encoding)) { if (function_exists('mb_convert_encoding')) { $target = mb_convert_encoding($target, $encoding, 'UTF-8'); } elseif (function_exists('iconv')) { $target = iconv('UTF-8', $encoding, $target); } else { throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).'); } } $catalogue->set((string) $source, $target, $domain); } $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Validates and parses the given file into a SimpleXMLElement * * @param string $file * * @throws \RuntimeException * * @return \SimpleXMLElement * * @throws InvalidResourceException */ private function parseFile($file) { try { $dom = XmlUtils::loadFile($file); } catch (\InvalidArgumentException $e) { throw new InvalidResourceException(sprintf('Unable to load "%s": %s', $file, $e->getMessage()), $e->getCode(), $e); } $internalErrors = libxml_use_internal_errors(true); $location = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd'; $parts = explode('/', $location); if (0 === stripos($location, 'phar://')) { $tmpfile = tempnam(sys_get_temp_dir(), 'sf2'); if ($tmpfile) { copy($location, $tmpfile); $parts = explode('/', str_replace('\\', '/', $tmpfile)); } } $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts)); $source = file_get_contents(__DIR__.'/schema/dic/xliff-core/xliff-core-1.2-strict.xsd'); $source = str_replace('http://www.w3.org/2001/xml.xsd', $location, $source); if (!@$dom->schemaValidateSource($source)) { throw new InvalidResourceException(implode("\n", $this->getXmlErrors($internalErrors))); } $dom->normalizeDocument(); libxml_use_internal_errors($internalErrors); return array(simplexml_import_dom($dom), strtoupper($dom->encoding)); } /** * Returns the XML errors of the internal XML parser * * @param Boolean $internalErrors * * @return array An array of errors */ private function getXmlErrors($internalErrors) { $errors = array(); foreach (libxml_get_errors() as $error) { $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', $error->code, trim($error->message), $error->file ? $error->file : 'n/a', $error->line, $error->column ); } libxml_clear_errors(); libxml_use_internal_errors($internalErrors); return $errors; } } PK]d<<"Translation/IdentityTranslator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * IdentityTranslator does not translate anything. * * @author Fabien Potencier * * @api */ class IdentityTranslator implements TranslatorInterface { private $selector; private $locale; /** * Constructor. * * @param MessageSelector|null $selector The message selector for pluralization * * @api */ public function __construct(MessageSelector $selector = null) { $this->selector = $selector ?: new MessageSelector(); } /** * {@inheritdoc} * * @api */ public function setLocale($locale) { $this->locale = $locale; } /** * {@inheritdoc} * * @api */ public function getLocale() { return $this->locale ?: \Locale::getDefault(); } /** * {@inheritdoc} * * @api */ public function trans($id, array $parameters = array(), $domain = null, $locale = null) { return strtr((string) $id, $parameters); } /** * {@inheritdoc} * * @api */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null) { return strtr($this->selector->choose((string) $id, (int) $number, $locale ?: $this->getLocale()), $parameters); } } PK]6",Translation/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Exception; /** * Exception interface for all exceptions thrown by the component. * * @author Fabien Potencier * * @api */ interface ExceptionInterface { } PK]DŽ2Translation/Exception/InvalidResourceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Exception; /** * Thrown when a resource cannot be loaded. * * @author Fabien Potencier * * @api */ class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface { } PK]2B3Translation/Exception/NotFoundResourceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Exception; /** * Thrown when a resource does not exist. * * @author Fabien Potencier * * @api */ class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface { } PK]%Mt&Translation/MetadataAwareInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * MetadataAwareInterface. * * @author Fabien Potencier */ interface MetadataAwareInterface { /** * Gets metadata for the given domain and key. * * Passing an empty domain will return an array with all metadata indexed by * domain and then by key. Passing an empty key will return an array with all * metadata for the given domain. * * @param string $domain The domain name * @param string $key The key * * @return mixed The value that was set or an array with the domains/keys or null */ public function getMetadata($key = '', $domain = 'messages'); /** * Adds metadata to a message domain. * * @param string $key The key * @param mixed $value The value * @param string $domain The domain name */ public function setMetadata($key, $value, $domain = 'messages'); /** * Deletes metadata for the given key and domain. * * Passing an empty domain will delete all metadata. Passing an empty key will * delete all metadata for the given domain. * * @param string $domain The domain name * @param string $key The key */ public function deleteMetadata($key = '', $domain = 'messages'); } PK]y4 Translation/MessageCatalogue.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; use Symfony\Component\Config\Resource\ResourceInterface; /** * MessageCatalogue. * * @author Fabien Potencier * * @api */ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface { private $messages = array(); private $metadata = array(); private $resources = array(); private $locale; private $fallbackCatalogue; private $parent; /** * Constructor. * * @param string $locale The locale * @param array $messages An array of messages classified by domain * * @api */ public function __construct($locale, array $messages = array()) { $this->locale = $locale; $this->messages = $messages; } /** * {@inheritdoc} * * @api */ public function getLocale() { return $this->locale; } /** * {@inheritdoc} * * @api */ public function getDomains() { return array_keys($this->messages); } /** * {@inheritdoc} * * @api */ public function all($domain = null) { if (null === $domain) { return $this->messages; } return isset($this->messages[$domain]) ? $this->messages[$domain] : array(); } /** * {@inheritdoc} * * @api */ public function set($id, $translation, $domain = 'messages') { $this->add(array($id => $translation), $domain); } /** * {@inheritdoc} * * @api */ public function has($id, $domain = 'messages') { if (isset($this->messages[$domain][$id])) { return true; } if (null !== $this->fallbackCatalogue) { return $this->fallbackCatalogue->has($id, $domain); } return false; } /** * {@inheritdoc} */ public function defines($id, $domain = 'messages') { return isset($this->messages[$domain][$id]); } /** * {@inheritdoc} * * @api */ public function get($id, $domain = 'messages') { if (isset($this->messages[$domain][$id])) { return $this->messages[$domain][$id]; } if (null !== $this->fallbackCatalogue) { return $this->fallbackCatalogue->get($id, $domain); } return $id; } /** * {@inheritdoc} * * @api */ public function replace($messages, $domain = 'messages') { $this->messages[$domain] = array(); $this->add($messages, $domain); } /** * {@inheritdoc} * * @api */ public function add($messages, $domain = 'messages') { if (!isset($this->messages[$domain])) { $this->messages[$domain] = $messages; } else { $this->messages[$domain] = array_replace($this->messages[$domain], $messages); } } /** * {@inheritdoc} * * @api */ public function addCatalogue(MessageCatalogueInterface $catalogue) { if ($catalogue->getLocale() !== $this->locale) { throw new \LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s"', $catalogue->getLocale(), $this->locale)); } foreach ($catalogue->all() as $domain => $messages) { $this->add($messages, $domain); } foreach ($catalogue->getResources() as $resource) { $this->addResource($resource); } if ($catalogue instanceof MetadataAwareInterface) { $metadata = $catalogue->getMetadata('', ''); $this->addMetadata($metadata); } } /** * {@inheritdoc} * * @api */ public function addFallbackCatalogue(MessageCatalogueInterface $catalogue) { // detect circular references $c = $this; do { if ($c->getLocale() === $catalogue->getLocale()) { throw new \LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale())); } } while ($c = $c->parent); $catalogue->parent = $this; $this->fallbackCatalogue = $catalogue; foreach ($catalogue->getResources() as $resource) { $this->addResource($resource); } } /** * {@inheritdoc} * * @api */ public function getFallbackCatalogue() { return $this->fallbackCatalogue; } /** * {@inheritdoc} * * @api */ public function getResources() { return array_values($this->resources); } /** * {@inheritdoc} * * @api */ public function addResource(ResourceInterface $resource) { $this->resources[$resource->__toString()] = $resource; } /** * {@inheritdoc} */ public function getMetadata($key = '', $domain = 'messages') { if ('' == $domain) { return $this->metadata; } if (isset($this->metadata[$domain])) { if ('' == $key) { return $this->metadata[$domain]; } if (isset($this->metadata[$domain][$key])) { return $this->metadata[$domain][$key]; } } return null; } /** * {@inheritdoc} */ public function setMetadata($key, $value, $domain = 'messages') { $this->metadata[$domain][$key] = $value; } /** * {@inheritdoc} */ public function deleteMetadata($key = '', $domain = 'messages') { if ('' == $domain) { $this->metadata = array(); } elseif ('' == $key) { unset($this->metadata[$domain]); } else { unset($this->metadata[$domain][$key]); } } /** * Adds current values with the new values. * * @param array $values Values to add */ private function addMetadata(array $values) { foreach ($values as $domain => $keys) { foreach ($keys as $key => $value) { $this->setMetadata($key, $value, $domain); } } } } PK]֛)Translation/MessageCatalogueInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; use Symfony\Component\Config\Resource\ResourceInterface; /** * MessageCatalogueInterface. * * @author Fabien Potencier * * @api */ interface MessageCatalogueInterface { /** * Gets the catalogue locale. * * @return string The locale * * @api */ public function getLocale(); /** * Gets the domains. * * @return array An array of domains * * @api */ public function getDomains(); /** * Gets the messages within a given domain. * * If $domain is null, it returns all messages. * * @param string $domain The domain name * * @return array An array of messages * * @api */ public function all($domain = null); /** * Sets a message translation. * * @param string $id The message id * @param string $translation The messages translation * @param string $domain The domain name * * @api */ public function set($id, $translation, $domain = 'messages'); /** * Checks if a message has a translation. * * @param string $id The message id * @param string $domain The domain name * * @return Boolean true if the message has a translation, false otherwise * * @api */ public function has($id, $domain = 'messages'); /** * Checks if a message has a translation (it does not take into account the fallback mechanism). * * @param string $id The message id * @param string $domain The domain name * * @return Boolean true if the message has a translation, false otherwise * * @api */ public function defines($id, $domain = 'messages'); /** * Gets a message translation. * * @param string $id The message id * @param string $domain The domain name * * @return string The message translation * * @api */ public function get($id, $domain = 'messages'); /** * Sets translations for a given domain. * * @param array $messages An array of translations * @param string $domain The domain name * * @api */ public function replace($messages, $domain = 'messages'); /** * Adds translations for a given domain. * * @param array $messages An array of translations * @param string $domain The domain name * * @api */ public function add($messages, $domain = 'messages'); /** * Merges translations from the given Catalogue into the current one. * * The two catalogues must have the same locale. * * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance * * @api */ public function addCatalogue(MessageCatalogueInterface $catalogue); /** * Merges translations from the given Catalogue into the current one * only when the translation does not exist. * * This is used to provide default translations when they do not exist for the current locale. * * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance * * @api */ public function addFallbackCatalogue(MessageCatalogueInterface $catalogue); /** * Gets the fallback catalogue. * * @return MessageCatalogueInterface|null A MessageCatalogueInterface instance or null when no fallback has been set * * @api */ public function getFallbackCatalogue(); /** * Returns an array of resources loaded to build this collection. * * @return ResourceInterface[] An array of resources * * @api */ public function getResources(); /** * Adds a resource for this collection. * * @param ResourceInterface $resource A resource instance * * @api */ public function addResource(ResourceInterface $resource); } PK] * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * MessageSelector. * * @author Fabien Potencier * @author Bernhard Schussek * * @api */ class MessageSelector { /** * Given a message with different plural translations separated by a * pipe (|), this method returns the correct portion of the message based * on the given number, locale and the pluralization rules in the message * itself. * * The message supports two different types of pluralization rules: * * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples * indexed: There is one apple|There are %count% apples * * The indexed solution can also contain labels (e.g. one: There is one apple). * This is purely for making the translations more clear - it does not * affect the functionality. * * The two methods can also be mixed: * {0} There are no apples|one: There is one apple|more: There are %count% apples * * @param string $message The message being translated * @param integer $number The number of items represented for the message * @param string $locale The locale to use for choosing * * @return string * * @throws \InvalidArgumentException * * @api */ public function choose($message, $number, $locale) { $parts = explode('|', $message); $explicitRules = array(); $standardRules = array(); foreach ($parts as $part) { $part = trim($part); if (preg_match('/^(?P'.Interval::getIntervalRegexp().')\s*(?P.*?)$/x', $part, $matches)) { $explicitRules[$matches['interval']] = $matches['message']; } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) { $standardRules[] = $matches[1]; } else { $standardRules[] = $part; } } // try to match an explicit rule, then fallback to the standard ones foreach ($explicitRules as $interval => $m) { if (Interval::test($number, $interval)) { return $m; } } $position = PluralizationRules::get($number, $locale); if (!isset($standardRules[$position])) { // when there's exactly one rule given, and that rule is a standard // rule, use this rule if (1 === count($parts) && isset($standardRules[0])) { return $standardRules[0]; } throw new \InvalidArgumentException(sprintf('Unable to choose a translation for "%s" with locale "%s". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $message, $locale)); } return $standardRules[$position]; } } PK]eGTranslation/Translator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; use Symfony\Component\Translation\Loader\LoaderInterface; use Symfony\Component\Translation\Exception\NotFoundResourceException; /** * Translator. * * @author Fabien Potencier * * @api */ class Translator implements TranslatorInterface { /** * @var MessageCatalogueInterface[] */ protected $catalogues = array(); /** * @var string */ protected $locale; /** * @var array */ private $fallbackLocales = array(); /** * @var LoaderInterface[] */ private $loaders = array(); /** * @var array */ private $resources = array(); /** * @var MessageSelector */ private $selector; /** * Constructor. * * @param string $locale The locale * @param MessageSelector|null $selector The message selector for pluralization * * @api */ public function __construct($locale, MessageSelector $selector = null) { $this->locale = $locale; $this->selector = $selector ?: new MessageSelector(); } /** * Adds a Loader. * * @param string $format The name of the loader (@see addResource()) * @param LoaderInterface $loader A LoaderInterface instance * * @api */ public function addLoader($format, LoaderInterface $loader) { $this->loaders[$format] = $loader; } /** * Adds a Resource. * * @param string $format The name of the loader (@see addLoader()) * @param mixed $resource The resource name * @param string $locale The locale * @param string $domain The domain * * @api */ public function addResource($format, $resource, $locale, $domain = null) { if (null === $domain) { $domain = 'messages'; } $this->resources[$locale][] = array($format, $resource, $domain); if (in_array($locale, $this->fallbackLocales)) { $this->catalogues = array(); } else { unset($this->catalogues[$locale]); } } /** * {@inheritdoc} * * @api */ public function setLocale($locale) { $this->locale = $locale; } /** * {@inheritdoc} * * @api */ public function getLocale() { return $this->locale; } /** * Sets the fallback locale(s). * * @param string|array $locales The fallback locale(s) * * @deprecated since 2.3, to be removed in 3.0. Use setFallbackLocales() instead. * * @api */ public function setFallbackLocale($locales) { $this->setFallbackLocales(is_array($locales) ? $locales : array($locales)); } /** * Sets the fallback locales. * * @param array $locales The fallback locales * * @api */ public function setFallbackLocales(array $locales) { // needed as the fallback locales are linked to the already loaded catalogues $this->catalogues = array(); $this->fallbackLocales = $locales; } /** * Gets the fallback locales. * * @return array $locales The fallback locales * * @api */ public function getFallbackLocales() { return $this->fallbackLocales; } /** * {@inheritdoc} * * @api */ public function trans($id, array $parameters = array(), $domain = null, $locale = null) { if (null === $locale) { $locale = $this->getLocale(); } if (null === $domain) { $domain = 'messages'; } if (!isset($this->catalogues[$locale])) { $this->loadCatalogue($locale); } return strtr($this->catalogues[$locale]->get((string) $id, $domain), $parameters); } /** * {@inheritdoc} * * @api */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null) { if (null === $locale) { $locale = $this->getLocale(); } if (null === $domain) { $domain = 'messages'; } if (!isset($this->catalogues[$locale])) { $this->loadCatalogue($locale); } $id = (string) $id; $catalogue = $this->catalogues[$locale]; while (!$catalogue->defines($id, $domain)) { if ($cat = $catalogue->getFallbackCatalogue()) { $catalogue = $cat; $locale = $catalogue->getLocale(); } else { break; } } return strtr($this->selector->choose($catalogue->get($id, $domain), (int) $number, $locale), $parameters); } /** * Gets the loaders. * * @return array LoaderInterface[] */ protected function getLoaders() { return $this->loaders; } protected function loadCatalogue($locale) { try { $this->doLoadCatalogue($locale); } catch (NotFoundResourceException $e) { if (!$this->computeFallbackLocales($locale)) { throw $e; } } $this->loadFallbackCatalogues($locale); } private function doLoadCatalogue($locale) { $this->catalogues[$locale] = new MessageCatalogue($locale); if (isset($this->resources[$locale])) { foreach ($this->resources[$locale] as $resource) { if (!isset($this->loaders[$resource[0]])) { throw new \RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0])); } $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2])); } } } private function loadFallbackCatalogues($locale) { $current = $this->catalogues[$locale]; foreach ($this->computeFallbackLocales($locale) as $fallback) { if (!isset($this->catalogues[$fallback])) { $this->doLoadCatalogue($fallback); } $current->addFallbackCatalogue($this->catalogues[$fallback]); $current = $this->catalogues[$fallback]; } } protected function computeFallbackLocales($locale) { $locales = array(); foreach ($this->fallbackLocales as $fallback) { if ($fallback === $locale) { continue; } $locales[] = $fallback; } if (strrchr($locale, '_') !== false) { array_unshift($locales, substr($locale, 0, -strlen(strrchr($locale, '_')))); } return array_unique($locales); } } PK](Translation/Extractor/ChainExtractor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Extractor; use Symfony\Component\Translation\MessageCatalogue; /** * ChainExtractor extracts translation messages from template files. * * @author Michel Salib */ class ChainExtractor implements ExtractorInterface { /** * The extractors. * * @var ExtractorInterface[] */ private $extractors = array(); /** * Adds a loader to the translation extractor. * * @param string $format The format of the loader * @param ExtractorInterface $extractor The loader */ public function addExtractor($format, ExtractorInterface $extractor) { $this->extractors[$format] = $extractor; } /** * {@inheritDoc} */ public function setPrefix($prefix) { foreach ($this->extractors as $extractor) { $extractor->setPrefix($prefix); } } /** * {@inheritDoc} */ public function extract($directory, MessageCatalogue $catalogue) { foreach ($this->extractors as $extractor) { $extractor->extract($directory, $catalogue); } } } PK]ArP,Translation/Extractor/ExtractorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Extractor; use Symfony\Component\Translation\MessageCatalogue; /** * Extracts translation messages from a template directory to the catalogue. * New found messages are injected to the catalogue using the prefix. * * @author Michel Salib */ interface ExtractorInterface { /** * Extracts translation messages from a template directory to the catalogue. * * @param string $directory The path to look into * @param MessageCatalogue $catalogue The catalogue */ public function extract($directory, MessageCatalogue $catalogue); /** * Sets the prefix that should be used for new found messages. * * @param string $prefix The prefix */ public function setPrefix($prefix); } PK]qUUTranslation/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\MessageCatalogueInterface; /** * Base catalogues binary operation class. * * @author Jean-François Simon */ abstract class AbstractOperation implements OperationInterface { /** * @var MessageCatalogueInterface */ protected $source; /** * @var MessageCatalogueInterface */ protected $target; /** * @var MessageCatalogue */ protected $result; /** * @var null|array */ private $domains; /** * @var array */ protected $messages; /** * @param MessageCatalogueInterface $source * @param MessageCatalogueInterface $target * * @throws \LogicException */ public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target) { if ($source->getLocale() !== $target->getLocale()) { throw new \LogicException('Operated catalogues must belong to the same locale.'); } $this->source = $source; $this->target = $target; $this->result = new MessageCatalogue($source->getLocale()); $this->domains = null; $this->messages = array(); } /** * {@inheritdoc} */ public function getDomains() { if (null === $this->domains) { $this->domains = array_values(array_unique(array_merge($this->source->getDomains(), $this->target->getDomains()))); } return $this->domains; } /** * {@inheritdoc} */ public function getMessages($domain) { if (!in_array($domain, $this->getDomains())) { throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain)); } if (!isset($this->messages[$domain]['all'])) { $this->processDomain($domain); } return $this->messages[$domain]['all']; } /** * {@inheritdoc} */ public function getNewMessages($domain) { if (!in_array($domain, $this->getDomains())) { throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain)); } if (!isset($this->messages[$domain]['new'])) { $this->processDomain($domain); } return $this->messages[$domain]['new']; } /** * {@inheritdoc} */ public function getObsoleteMessages($domain) { if (!in_array($domain, $this->getDomains())) { throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain)); } if (!isset($this->messages[$domain]['obsolete'])) { $this->processDomain($domain); } return $this->messages[$domain]['obsolete']; } /** * {@inheritdoc} */ public function getResult() { foreach ($this->getDomains() as $domain) { if (!isset($this->messages[$domain])) { $this->processDomain($domain); } } return $this->result; } /** * @param string $domain */ abstract protected function processDomain($domain); } PK]Y[  ,Translation/Catalogue/OperationInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; use Symfony\Component\Translation\MessageCatalogueInterface; /** * Represents an operation on catalogue(s). * * @author Jean-François Simon */ interface OperationInterface { /** * Returns domains affected by operation. * * @return array */ public function getDomains(); /** * Returns all valid messages after operation. * * @param string $domain * * @return array */ public function getMessages($domain); /** * Returns new messages after operation. * * @param string $domain * * @return array */ public function getNewMessages($domain); /** * Returns obsolete messages after operation. * * @param string $domain * * @return array */ public function getObsoleteMessages($domain); /** * Returns resulting catalogue. * * @return MessageCatalogueInterface */ public function getResult(); } PK]س(Translation/Catalogue/MergeOperation.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; /** * Merge operation between two catalogues. * * @author Jean-François Simon */ class MergeOperation extends AbstractOperation { /** * {@inheritdoc} */ protected function processDomain($domain) { $this->messages[$domain] = array( 'all' => array(), 'new' => array(), 'obsolete' => array(), ); foreach ($this->source->all($domain) as $id => $message) { $this->messages[$domain]['all'][$id] = $message; $this->result->add(array($id => $message), $domain); } foreach ($this->target->all($domain) as $id => $message) { if (!$this->source->has($id, $domain)) { $this->messages[$domain]['all'][$id] = $message; $this->messages[$domain]['new'][$id] = $message; $this->result->add(array($id => $message), $domain); } } } } PK]ӄ'Translation/Catalogue/DiffOperation.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; /** * Diff operation between two catalogues. * * @author Jean-François Simon */ class DiffOperation extends AbstractOperation { /** * {@inheritdoc} */ protected function processDomain($domain) { $this->messages[$domain] = array( 'all' => array(), 'new' => array(), 'obsolete' => array(), ); foreach ($this->source->all($domain) as $id => $message) { if ($this->target->has($id, $domain)) { $this->messages[$domain]['all'][$id] = $message; $this->result->add(array($id => $message), $domain); } else { $this->messages[$domain]['obsolete'][$id] = $message; } } foreach ($this->target->all($domain) as $id => $message) { if (!$this->source->has($id, $domain)) { $this->messages[$domain]['all'][$id] = $message; $this->messages[$domain]['new'][$id] = $message; $this->result->add(array($id => $message), $domain); } } } } PK]3#Translation/TranslatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * TranslatorInterface. * * @author Fabien Potencier * * @api */ interface TranslatorInterface { /** * Translates the given message. * * @param string $id The message id (may also be an object that can be cast to string) * @param array $parameters An array of parameters for the message * @param string|null $domain The domain for the message or null to use the default * @param string|null $locale The locale or null to use the default * * @return string The translated string * * @api */ public function trans($id, array $parameters = array(), $domain = null, $locale = null); /** * Translates the given choice message by choosing a translation according to a number. * * @param string $id The message id (may also be an object that can be cast to string) * @param integer $number The number to use to find the indice of the message * @param array $parameters An array of parameters for the message * @param string|null $domain The domain for the message or null to use the default * @param string|null $locale The locale or null to use the default * * @return string The translated string * * @api */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null); /** * Sets the current locale. * * @param string $locale The locale * * @api */ public function setLocale($locale); /** * Returns the current locale. * * @return string The locale * * @api */ public function getLocale(); } PK]OO'Serializer/SerializerAwareInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer; /** * Defines the interface of encoders * * @author Jordi Boggiano */ interface SerializerAwareInterface { /** * Sets the owning Serializer object * * @param SerializerInterface $serializer */ public function setSerializer(SerializerInterface $serializer); } PK]"pyy-Serializer/Normalizer/NormalizerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; /** * Defines the interface of normalizers. * * @author Jordi Boggiano */ interface NormalizerInterface { /** * Normalizes an object into a set of arrays/scalars * * @param object $object object to normalize * @param string $format format the normalization result will be encoded as * @param array $context Context options for the normalizer * * @return array|scalar */ public function normalize($object, $format = null, array $context = array()); /** * Checks whether the given class is supported for normalization by this normalizer * * @param mixed $data Data to normalize. * @param string $format The format being (de-)serialized from or into. * * @return Boolean */ public function supportsNormalization($data, $format = null); } PK][i553Serializer/Normalizer/SerializerAwareNormalizer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\SerializerAwareInterface; /** * SerializerAware Normalizer implementation * * @author Jordi Boggiano */ abstract class SerializerAwareNormalizer implements SerializerAwareInterface { /** * @var SerializerInterface */ protected $serializer; /** * {@inheritdoc} */ public function setSerializer(SerializerInterface $serializer) { $this->serializer = $serializer; } } PK]qU1Serializer/Normalizer/DenormalizableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; /** * Defines the most basic interface a class must implement to be denormalizable * * If a denormalizer is registered for the class and it doesn't implement * the Denormalizable interfaces, the normalizer will be used instead * * @author Jordi Boggiano */ interface DenormalizableInterface { /** * Denormalizes the object back from an array of scalars|arrays. * * It is important to understand that the denormalize() call should denormalize * recursively all child objects of the implementor. * * @param DenormalizerInterface $denormalizer The denormalizer is given so that you * can use it to denormalize objects contained within this object. * @param array|scalar $data The data from which to re-create the object. * @param string|null $format The format is optionally given to be able to denormalize differently * based on different input formats. * @param array $context options for denormalizing */ public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array()); } PK]/Serializer/Normalizer/DenormalizerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; /** * Defines the interface of denormalizers. * * @author Jordi Boggiano */ interface DenormalizerInterface { /** * Denormalizes data back into an object of the given class * * @param mixed $data data to restore * @param string $class the expected class to instantiate * @param string $format format the given data was extracted from * @param array $context options available to the denormalizer * * @return object */ public function denormalize($data, $class, $format = null, array $context = array()); /** * Checks whether the given class is supported for denormalization by this normalizer * * @param mixed $data Data to denormalize from. * @param string $type The class to which the data should be denormalized. * @param string $format The format being deserialized from. * * @return Boolean */ public function supportsDenormalization($data, $type, $format = null); } PK]=Vxe::/Serializer/Normalizer/NormalizableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; /** * Defines the most basic interface a class must implement to be normalizable * * If a normalizer is registered for the class and it doesn't implement * the Normalizable interfaces, the normalizer will be used instead * * @author Jordi Boggiano */ interface NormalizableInterface { /** * Normalizes the object into an array of scalars|arrays. * * It is important to understand that the normalize() call should normalize * recursively all child objects of the implementor. * * @param NormalizerInterface $normalizer The normalizer is given so that you * can use it to normalize objects contained within this object. * @param string|null $format The format is optionally given to be able to normalize differently * based on different output formats. * @param array $context Options for normalizing this object * * @return array|scalar */ public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array()); } PK] ,,0Serializer/Normalizer/GetSetMethodNormalizer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Exception\RuntimeException; /** * Converts between objects with getter and setter methods and arrays. * * The normalization process looks at all public methods and calls the ones * which have a name starting with get and take no parameters. The result is a * map from property names (method name stripped of the get prefix and converted * to lower case) to property values. Property values are normalized through the * serializer. * * The denormalization first looks at the constructor of the given class to see * if any of the parameters have the same name as one of the properties. The * constructor is then called with all parameters or an exception is thrown if * any required parameters were not present as properties. Then the denormalizer * walks through the given map of property names to property values to see if a * setter method exists for any of the properties. If a setter exists it is * called with the property value. No automatic denormalization of the value * takes place. * * @author Nils Adermann */ class GetSetMethodNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface { protected $callbacks = array(); protected $ignoredAttributes = array(); protected $camelizedAttributes = array(); /** * Set normalization callbacks. * * @param callable[] $callbacks help normalize the result * * @throws InvalidArgumentException if a non-callable callback is set */ public function setCallbacks(array $callbacks) { foreach ($callbacks as $attribute => $callback) { if (!is_callable($callback)) { throw new InvalidArgumentException(sprintf('The given callback for attribute "%s" is not callable.', $attribute)); } } $this->callbacks = $callbacks; } /** * Set ignored attributes for normalization * * @param array $ignoredAttributes */ public function setIgnoredAttributes(array $ignoredAttributes) { $this->ignoredAttributes = $ignoredAttributes; } /** * Set attributes to be camelized on denormalize * * @param array $camelizedAttributes */ public function setCamelizedAttributes(array $camelizedAttributes) { $this->camelizedAttributes = $camelizedAttributes; } /** * {@inheritdoc} */ public function normalize($object, $format = null, array $context = array()) { $reflectionObject = new \ReflectionObject($object); $reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC); $attributes = array(); foreach ($reflectionMethods as $method) { if ($this->isGetMethod($method)) { $attributeName = lcfirst(substr($method->name, 3)); if (in_array($attributeName, $this->ignoredAttributes)) { continue; } $attributeValue = $method->invoke($object); if (array_key_exists($attributeName, $this->callbacks)) { $attributeValue = call_user_func($this->callbacks[$attributeName], $attributeValue); } if (null !== $attributeValue && !is_scalar($attributeValue)) { if (!$this->serializer instanceof NormalizerInterface) { throw new \LogicException(sprintf('Cannot normalize attribute "%s" because injected serializer is not a normalizer', $attributeName)); } $attributeValue = $this->serializer->normalize($attributeValue, $format); } $attributes[$attributeName] = $attributeValue; } } return $attributes; } /** * {@inheritdoc} */ public function denormalize($data, $class, $format = null, array $context = array()) { $reflectionClass = new \ReflectionClass($class); $constructor = $reflectionClass->getConstructor(); if ($constructor) { $constructorParameters = $constructor->getParameters(); $params = array(); foreach ($constructorParameters as $constructorParameter) { $paramName = lcfirst($this->formatAttribute($constructorParameter->name)); if (isset($data[$paramName])) { $params[] = $data[$paramName]; // don't run set for a parameter passed to the constructor unset($data[$paramName]); } elseif (!$constructorParameter->isOptional()) { throw new RuntimeException( 'Cannot create an instance of '.$class. ' from serialized data because its constructor requires '. 'parameter "'.$constructorParameter->name. '" to be present.'); } } $object = $reflectionClass->newInstanceArgs($params); } else { $object = new $class; } foreach ($data as $attribute => $value) { $setter = 'set'.$this->formatAttribute($attribute); if (method_exists($object, $setter)) { $object->$setter($value); } } return $object; } /** * Format attribute name to access parameters or methods * As option, if attribute name is found on camelizedAttributes array * returns attribute name in camelcase format * * @param string $attributeName * @return string */ protected function formatAttribute($attributeName) { if (in_array($attributeName, $this->camelizedAttributes)) { return preg_replace_callback( '/(^|_|\.)+(.)/', function ($match) { return ('.' === $match[1] ? '_' : '').strtoupper($match[2]); }, $attributeName ); } return $attributeName; } /** * {@inheritDoc} */ public function supportsNormalization($data, $format = null) { return is_object($data) && $this->supports(get_class($data)); } /** * {@inheritDoc} */ public function supportsDenormalization($data, $type, $format = null) { return $this->supports($type); } /** * Checks if the given class has any get{Property} method. * * @param string $class * * @return Boolean */ private function supports($class) { $class = new \ReflectionClass($class); $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC); foreach ($methods as $method) { if ($this->isGetMethod($method)) { return true; } } return false; } /** * Checks if a method's name is get.* and can be called without parameters. * * @param \ReflectionMethod $method the method to check * * @return Boolean whether the method is a getter. */ private function isGetMethod(\ReflectionMethod $method) { return ( 0 === strpos($method->name, 'get') && 3 < strlen($method->name) && 0 === $method->getNumberOfRequiredParameters() ); } } PK]SVV*Serializer/Normalizer/CustomNormalizer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; /** * @author Jordi Boggiano */ class CustomNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface { /** * {@inheritdoc} */ public function normalize($object, $format = null, array $context = array()) { return $object->normalize($this->serializer, $format, $context); } /** * {@inheritdoc} */ public function denormalize($data, $class, $format = null, array $context = array()) { $object = new $class(); $object->denormalize($this->serializer, $data, $format, $context); return $object; } /** * Checks if the given class implements the NormalizableInterface. * * @param mixed $data Data to normalize. * @param string $format The format being (de-)serialized from or into. * * @return Boolean */ public function supportsNormalization($data, $format = null) { return $data instanceof NormalizableInterface; } /** * Checks if the given class implements the NormalizableInterface. * * @param mixed $data Data to denormalize from. * @param string $type The class to which the data should be denormalized. * @param string $format The format being deserialized from. * * @return Boolean */ public function supportsDenormalization($data, $type, $format = null) { $class = new \ReflectionClass($type); return $class->isSubclassOf('Symfony\Component\Serializer\Normalizer\DenormalizableInterface'); } } PK]J'Serializer/Exception/LogicException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * LogicException * * @author Lukas Kahwe Smith */ class LogicException extends \LogicException implements Exception { } PK]h=)Serializer/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * RuntimeException * * @author Johannes M. Schmitt */ class RuntimeException extends \RuntimeException implements Exception { } PK]^L-Serializer/Exception/UnsupportedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * UnsupportedException * * @author Johannes M. Schmitt */ class UnsupportedException extends InvalidArgumentException { } PK][1Serializer/Exception/UnexpectedValueException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * UnexpectedValueException * * @author Lukas Kahwe Smith */ class UnexpectedValueException extends \UnexpectedValueException implements Exception { } PK]AA "Serializer/Exception/Exception.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * Base exception * * @author Johannes M. Schmitt */ interface Exception { } PK]TY1Serializer/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * InvalidArgumentException * * @author Johannes M. Schmitt */ class InvalidArgumentException extends \InvalidArgumentException implements Exception { } PK]ʪ2 /&/&Serializer/Serializer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer; use Symfony\Component\Serializer\Encoder\ChainDecoder; use Symfony\Component\Serializer\Encoder\ChainEncoder; use Symfony\Component\Serializer\Encoder\EncoderInterface; use Symfony\Component\Serializer\Encoder\DecoderInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Exception\RuntimeException; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Exception\UnexpectedValueException; /** * Serializer serializes and deserializes data * * objects are turned into arrays by normalizers * arrays are turned into various output formats by encoders * * $serializer->serialize($obj, 'xml') * $serializer->decode($data, 'xml') * $serializer->denormalize($data, 'Class', 'xml') * * @author Jordi Boggiano * @author Johannes M. Schmitt * @author Lukas Kahwe Smith */ class Serializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface { protected $encoder; protected $decoder; protected $normalizers = array(); protected $normalizerCache = array(); protected $denormalizerCache = array(); public function __construct(array $normalizers = array(), array $encoders = array()) { foreach ($normalizers as $normalizer) { if ($normalizer instanceof SerializerAwareInterface) { $normalizer->setSerializer($this); } } $this->normalizers = $normalizers; $decoders = array(); $realEncoders = array(); foreach ($encoders as $encoder) { if ($encoder instanceof SerializerAwareInterface) { $encoder->setSerializer($this); } if ($encoder instanceof DecoderInterface) { $decoders[] = $encoder; } if ($encoder instanceof EncoderInterface) { $realEncoders[] = $encoder; } } $this->encoder = new ChainEncoder($realEncoders); $this->decoder = new ChainDecoder($decoders); } /** * {@inheritdoc} */ final public function serialize($data, $format, array $context = array()) { if (!$this->supportsEncoding($format)) { throw new UnexpectedValueException(sprintf('Serialization for the format %s is not supported', $format)); } if ($this->encoder->needsNormalization($format)) { $data = $this->normalize($data, $format, $context); } return $this->encode($data, $format, $context); } /** * {@inheritdoc} */ final public function deserialize($data, $type, $format, array $context = array()) { if (!$this->supportsDecoding($format)) { throw new UnexpectedValueException(sprintf('Deserialization for the format %s is not supported', $format)); } $data = $this->decode($data, $format, $context); return $this->denormalize($data, $type, $format, $context); } /** * {@inheritdoc} */ public function normalize($data, $format = null, array $context = array()) { if (null === $data || is_scalar($data)) { return $data; } if (is_object($data) && $this->supportsNormalization($data, $format)) { return $this->normalizeObject($data, $format, $context); } if ($data instanceof \Traversable) { $normalized = array(); foreach ($data as $key => $val) { $normalized[$key] = $this->normalize($val, $format, $context); } return $normalized; } if (is_object($data)) { return $this->normalizeObject($data, $format, $context); } if (is_array($data)) { foreach ($data as $key => $val) { $data[$key] = $this->normalize($val, $format, $context); } return $data; } throw new UnexpectedValueException(sprintf('An unexpected value could not be normalized: %s', var_export($data, true))); } /** * {@inheritdoc} */ public function denormalize($data, $type, $format = null, array $context = array()) { return $this->denormalizeObject($data, $type, $format, $context); } /** * {@inheritdoc} */ public function supportsNormalization($data, $format = null) { try { $this->getNormalizer($data, $format); } catch (RuntimeException $e) { return false; } return true; } /** * {@inheritdoc} */ public function supportsDenormalization($data, $type, $format = null) { try { $this->getDenormalizer($data, $type, $format = null); } catch (RuntimeException $e) { return false; } return true; } /** * {@inheritdoc} */ private function getNormalizer($data, $format = null) { foreach ($this->normalizers as $normalizer) { if ($normalizer instanceof NormalizerInterface && $normalizer->supportsNormalization($data, $format)) { return $normalizer; } } throw new RuntimeException(sprintf('No normalizer found for format "%s".', $format)); } /** * {@inheritdoc} */ private function getDenormalizer($data, $type, $format = null) { foreach ($this->normalizers as $normalizer) { if ($normalizer instanceof DenormalizerInterface && $normalizer->supportsDenormalization($data, $type, $format)) { return $normalizer; } } throw new RuntimeException(sprintf('No denormalizer found for format "%s".', $format)); } /** * {@inheritdoc} */ final public function encode($data, $format, array $context = array()) { return $this->encoder->encode($data, $format, $context); } /** * {@inheritdoc} */ final public function decode($data, $format, array $context = array()) { return $this->decoder->decode($data, $format, $context); } /** * Normalizes an object into a set of arrays/scalars * * @param object $object object to normalize * @param string $format format name, present to give the option to normalizers to act differently based on formats * @param array $context The context data for this particular normalization * * @return array|scalar * * @throws LogicException * @throws UnexpectedValueException */ private function normalizeObject($object, $format = null, array $context = array()) { if (!$this->normalizers) { throw new LogicException('You must register at least one normalizer to be able to normalize objects.'); } $class = get_class($object); if (isset($this->normalizerCache[$class][$format])) { return $this->normalizerCache[$class][$format]->normalize($object, $format, $context); } foreach ($this->normalizers as $normalizer) { if ($normalizer instanceof NormalizerInterface && $normalizer->supportsNormalization($object, $format)) { $this->normalizerCache[$class][$format] = $normalizer; return $normalizer->normalize($object, $format, $context); } } throw new UnexpectedValueException(sprintf('Could not normalize object of type %s, no supporting normalizer found.', $class)); } /** * Denormalizes data back into an object of the given class * * @param mixed $data data to restore * @param string $class the expected class to instantiate * @param string $format format name, present to give the option to normalizers to act differently based on formats * @param array $context The context data for this particular denormalization * * @return object * * @throws LogicException * @throws UnexpectedValueException */ private function denormalizeObject($data, $class, $format = null, array $context = array()) { if (!$this->normalizers) { throw new LogicException('You must register at least one normalizer to be able to denormalize objects.'); } if (isset($this->denormalizerCache[$class][$format])) { return $this->denormalizerCache[$class][$format]->denormalize($data, $class, $format, $context); } foreach ($this->normalizers as $normalizer) { if ($normalizer instanceof DenormalizerInterface && $normalizer->supportsDenormalization($data, $class, $format)) { $this->denormalizerCache[$class][$format] = $normalizer; return $normalizer->denormalize($data, $class, $format, $context); } } throw new UnexpectedValueException(sprintf('Could not denormalize object of type %s, no supporting normalizer found.', $class)); } /** * {@inheritdoc} */ public function supportsEncoding($format) { return $this->encoder->supportsEncoding($format); } /** * {@inheritdoc} */ public function supportsDecoding($format) { return $this->decoder->supportsDecoding($format); } } PK][55!Serializer/Encoder/XmlEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; use Symfony\Component\Serializer\Exception\UnexpectedValueException; /** * Encodes XML data * * @author Jordi Boggiano * @author John Wards * @author Fabian Vogler */ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, DecoderInterface, NormalizationAwareInterface { private $dom; private $format; private $context; private $rootNodeName = 'response'; /** * Construct new XmlEncoder and allow to change the root node element name. * * @param string $rootNodeName */ public function __construct($rootNodeName = 'response') { $this->rootNodeName = $rootNodeName; } /** * {@inheritdoc} */ public function encode($data, $format, array $context = array()) { if ($data instanceof \DOMDocument) { return $data->saveXML(); } $xmlRootNodeName = $this->resolveXmlRootName($context); $this->dom = $this->createDomDocument($context); $this->format = $format; $this->context = $context; if (null !== $data && !is_scalar($data)) { $root = $this->dom->createElement($xmlRootNodeName); $this->dom->appendChild($root); $this->buildXml($root, $data, $xmlRootNodeName); } else { $this->appendNode($this->dom, $data, $xmlRootNodeName); } return $this->dom->saveXML(); } /** * {@inheritdoc} */ public function decode($data, $format, array $context = array()) { if ('' === trim($data)) { throw new UnexpectedValueException('Invalid XML data, it can not be empty.'); } $internalErrors = libxml_use_internal_errors(true); $disableEntities = libxml_disable_entity_loader(true); libxml_clear_errors(); $dom = new \DOMDocument(); $dom->loadXML($data, LIBXML_NONET); libxml_use_internal_errors($internalErrors); libxml_disable_entity_loader($disableEntities); if ($error = libxml_get_last_error()) { libxml_clear_errors(); throw new UnexpectedValueException($error->message); } foreach ($dom->childNodes as $child) { if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { throw new UnexpectedValueException('Document types are not allowed.'); } } $xml = simplexml_import_dom($dom); if ($error = libxml_get_last_error()) { throw new UnexpectedValueException($error->message); } if (!$xml->count()) { if (!$xml->attributes()) { return (string) $xml; } $data = array(); foreach ($xml->attributes() as $attrkey => $attr) { $data['@'.$attrkey] = (string) $attr; } $data['#'] = (string) $xml; return $data; } return $this->parseXml($xml); } /** * {@inheritdoc} */ public function supportsEncoding($format) { return 'xml' === $format; } /** * {@inheritdoc} */ public function supportsDecoding($format) { return 'xml' === $format; } /** * Sets the root node name * * @param string $name root node name */ public function setRootNodeName($name) { $this->rootNodeName = $name; } /** * Returns the root node name * @return string */ public function getRootNodeName() { return $this->rootNodeName; } /** * @param \DOMNode $node * @param string $val * * @return Boolean */ final protected function appendXMLString(\DOMNode $node, $val) { if (strlen($val) > 0) { $frag = $this->dom->createDocumentFragment(); $frag->appendXML($val); $node->appendChild($frag); return true; } return false; } /** * @param \DOMNode $node * @param string $val * * @return Boolean */ final protected function appendText(\DOMNode $node, $val) { $nodeText = $this->dom->createTextNode($val); $node->appendChild($nodeText); return true; } /** * @param \DOMNode $node * @param string $val * * @return Boolean */ final protected function appendCData(\DOMNode $node, $val) { $nodeText = $this->dom->createCDATASection($val); $node->appendChild($nodeText); return true; } /** * @param \DOMNode $node * @param \DOMDocumentFragment $fragment * * @return Boolean */ final protected function appendDocumentFragment(\DOMNode $node, $fragment) { if ($fragment instanceof \DOMDocumentFragment) { $node->appendChild($fragment); return true; } return false; } /** * Checks the name is a valid xml element name * * @param string $name * * @return Boolean */ final protected function isElementNameValid($name) { return $name && false === strpos($name, ' ') && preg_match('#^[\pL_][\pL0-9._-]*$#ui', $name); } /** * Parse the input SimpleXmlElement into an array. * * @param \SimpleXmlElement $node xml to parse * * @return array */ private function parseXml(\SimpleXmlElement $node) { $data = array(); if ($node->attributes()) { foreach ($node->attributes() as $attrkey => $attr) { $data['@'.$attrkey] = (string) $attr; } } foreach ($node->children() as $key => $subnode) { if ($subnode->count()) { $value = $this->parseXml($subnode); } elseif ($subnode->attributes()) { $value = array(); foreach ($subnode->attributes() as $attrkey => $attr) { $value['@'.$attrkey] = (string) $attr; } $value['#'] = (string) $subnode; } else { $value = (string) $subnode; } if ($key === 'item') { if (isset($value['@key'])) { if (isset($value['#'])) { $data[$value['@key']] = $value['#']; } else { $data[$value['@key']] = $value; } } else { $data['item'][] = $value; } } elseif (array_key_exists($key, $data) || $key == "entry") { if ((false === is_array($data[$key])) || (false === isset($data[$key][0]))) { $data[$key] = array($data[$key]); } $data[$key][] = $value; } else { $data[$key] = $value; } } return $data; } /** * Parse the data and convert it to DOMElements * * @param \DOMNode $parentNode * @param array|object $data * @param string|null $xmlRootNodeName * * @return Boolean * * @throws UnexpectedValueException */ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null) { $append = true; if (is_array($data) || $data instanceof \Traversable) { foreach ($data as $key => $data) { //Ah this is the magic @ attribute types. if (0 === strpos($key, "@") && is_scalar($data) && $this->isElementNameValid($attributeName = substr($key, 1))) { $parentNode->setAttribute($attributeName, $data); } elseif ($key === '#') { $append = $this->selectNodeType($parentNode, $data); } elseif (is_array($data) && false === is_numeric($key)) { /** * Is this array fully numeric keys? */ if (ctype_digit(implode('', array_keys($data)))) { /** * Create nodes to append to $parentNode based on the $key of this array * Produces 01 * From array("item" => array(0,1)); */ foreach ($data as $subData) { $append = $this->appendNode($parentNode, $subData, $key); } } else { $append = $this->appendNode($parentNode, $data, $key); } } elseif (is_numeric($key) || !$this->isElementNameValid($key)) { $append = $this->appendNode($parentNode, $data, "item", $key); } else { $append = $this->appendNode($parentNode, $data, $key); } } return $append; } if (is_object($data)) { $data = $this->serializer->normalize($data, $this->format, $this->context); if (null !== $data && !is_scalar($data)) { return $this->buildXml($parentNode, $data, $xmlRootNodeName); } // top level data object was normalized into a scalar if (!$parentNode->parentNode->parentNode) { $root = $parentNode->parentNode; $root->removeChild($parentNode); return $this->appendNode($root, $data, $xmlRootNodeName); } return $this->appendNode($parentNode, $data, 'data'); } throw new UnexpectedValueException(sprintf('An unexpected value could not be serialized: %s', var_export($data, true))); } /** * Selects the type of node to create and appends it to the parent. * * @param \DOMNode $parentNode * @param array|object $data * @param string $nodeName * @param string $key * * @return Boolean */ private function appendNode(\DOMNode $parentNode, $data, $nodeName, $key = null) { $node = $this->dom->createElement($nodeName); if (null !== $key) { $node->setAttribute('key', $key); } $appendNode = $this->selectNodeType($node, $data); // we may have decided not to append this node, either in error or if its $nodeName is not valid if ($appendNode) { $parentNode->appendChild($node); } return $appendNode; } /** * Checks if a value contains any characters which would require CDATA wrapping. * * @param string $val * * @return Boolean */ private function needsCdataWrapping($val) { return preg_match('/[<>&]/', $val); } /** * Tests the value being passed and decide what sort of element to create * * @param \DOMNode $node * @param mixed $val * * @return Boolean */ private function selectNodeType(\DOMNode $node, $val) { if (is_array($val)) { return $this->buildXml($node, $val); } elseif ($val instanceof \SimpleXMLElement) { $child = $this->dom->importNode(dom_import_simplexml($val), true); $node->appendChild($child); } elseif ($val instanceof \Traversable) { $this->buildXml($node, $val); } elseif (is_object($val)) { return $this->buildXml($node, $this->serializer->normalize($val, $this->format, $this->context)); } elseif (is_numeric($val)) { return $this->appendText($node, (string) $val); } elseif (is_string($val) && $this->needsCdataWrapping($val)) { return $this->appendCData($node, $val); } elseif (is_string($val)) { return $this->appendText($node, $val); } elseif (is_bool($val)) { return $this->appendText($node, (int) $val); } elseif ($val instanceof \DOMNode) { $child = $this->dom->importNode($val, true); $node->appendChild($child); } return true; } /** * Get real XML root node name, taking serializer options into account. */ private function resolveXmlRootName(array $context = array()) { return isset($context['xml_root_node_name']) ? $context['xml_root_node_name'] : $this->rootNodeName; } /** * Create a DOM document, taking serializer options into account. * * @param array $context options that the encoder has access to. * * @return \DOMDocument */ private function createDomDocument(array $context) { $document = new \DOMDocument(); // Set an attribute on the DOM document specifying, as part of the XML declaration, $xmlOptions = array( // the version number of the document 'xml_version' => 'xmlVersion', // the encoding of the document 'xml_encoding' => 'encoding', // whether the document is standalone 'xml_standalone' => 'xmlStandalone', ); foreach ($xmlOptions as $xmlOption => $documentProperty) { if (isset($context[$xmlOption])) { $document->$documentProperty = $context[$xmlOption]; } } return $document; } } PK]VO#Serializer/Encoder/ChainDecoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; use Symfony\Component\Serializer\Exception\RuntimeException; /** * Decoder delegating the decoding to a chain of decoders. * * @author Jordi Boggiano * @author Johannes M. Schmitt * @author Lukas Kahwe Smith */ class ChainDecoder implements DecoderInterface { protected $decoders = array(); protected $decoderByFormat = array(); public function __construct(array $decoders = array()) { $this->decoders = $decoders; } /** * {@inheritdoc} */ final public function decode($data, $format, array $context = array()) { return $this->getDecoder($format)->decode($data, $format, $context); } /** * {@inheritdoc} */ public function supportsDecoding($format) { try { $this->getDecoder($format); } catch (RuntimeException $e) { return false; } return true; } /** * Gets the decoder supporting the format. * * @param string $format * * @return DecoderInterface * @throws RuntimeException if no decoder is found */ private function getDecoder($format) { if (isset($this->decoderByFormat[$format]) && isset($this->decoders[$this->decoderByFormat[$format]]) ) { return $this->decoders[$this->decoderByFormat[$format]]; } foreach ($this->decoders as $i => $decoder) { if ($decoder->supportsDecoding($format)) { $this->decoderByFormat[$format] = $i; return $decoder; } } throw new RuntimeException(sprintf('No decoder found for format "%s".', $format)); } } PK]S R #Serializer/Encoder/ChainEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; use Symfony\Component\Serializer\Exception\RuntimeException; /** * Encoder delegating the decoding to a chain of encoders. * * @author Jordi Boggiano * @author Johannes M. Schmitt * @author Lukas Kahwe Smith */ class ChainEncoder implements EncoderInterface { protected $encoders = array(); protected $encoderByFormat = array(); public function __construct(array $encoders = array()) { $this->encoders = $encoders; } /** * {@inheritdoc} */ final public function encode($data, $format, array $context = array()) { return $this->getEncoder($format)->encode($data, $format, $context); } /** * {@inheritdoc} */ public function supportsEncoding($format) { try { $this->getEncoder($format); } catch (RuntimeException $e) { return false; } return true; } /** * Checks whether the normalization is needed for the given format. * * @param string $format * * @return Boolean */ public function needsNormalization($format) { $encoder = $this->getEncoder($format); if (!$encoder instanceof NormalizationAwareInterface) { return true; } if ($encoder instanceof self) { return $encoder->needsNormalization($format); } return false; } /** * Gets the encoder supporting the format. * * @param string $format * * @return EncoderInterface * @throws RuntimeException if no encoder is found */ private function getEncoder($format) { if (isset($this->encoderByFormat[$format]) && isset($this->encoders[$this->encoderByFormat[$format]]) ) { return $this->encoders[$this->encoderByFormat[$format]]; } foreach ($this->encoders as $i => $encoder) { if ($encoder->supportsEncoding($format)) { $this->encoderByFormat[$format] = $i; return $encoder; } } throw new RuntimeException(sprintf('No encoder found for format "%s".', $format)); } } PK]@!Serializer/Encoder/JsonDecode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Decodes JSON data * * @author Sander Coolen */ class JsonDecode implements DecoderInterface { /** * Specifies if the returned result should be an associative array or a nested stdClass object hierarchy. * * @var Boolean */ private $associative; /** * Specifies the recursion depth. * * @var integer */ private $recursionDepth; private $lastError = JSON_ERROR_NONE; protected $serializer; /** * Constructs a new JsonDecode instance. * * @param Boolean $associative True to return the result associative array, false for a nested stdClass hierarchy * @param integer $depth Specifies the recursion depth */ public function __construct($associative = false, $depth = 512) { $this->associative = $associative; $this->recursionDepth = (int) $depth; } /** * Returns the last decoding error (if any). * * @return integer * * @see http://php.net/manual/en/function.json-last-error.php json_last_error */ public function getLastError() { return $this->lastError; } /** * Decodes data. * * @param string $data The encoded JSON string to decode * @param string $format Must be set to JsonEncoder::FORMAT * @param array $context An optional set of options for the JSON decoder; see below * * The $context array is a simple key=>value array, with the following supported keys: * * json_decode_associative: boolean * If true, returns the object as associative array. * If false, returns the object as nested stdClass * If not specified, this method will use the default set in JsonDecode::__construct * * json_decode_recursion_depth: integer * Specifies the maximum recursion depth * If not specified, this method will use the default set in JsonDecode::__construct * * json_decode_options: integer * Specifies additional options as per documentation for json_decode. Only supported with PHP 5.4.0 and higher * * @return mixed * * @see http://php.net/json_decode json_decode */ public function decode($data, $format, array $context = array()) { $context = $this->resolveContext($context); $associative = $context['json_decode_associative']; $recursionDepth = $context['json_decode_recursion_depth']; $options = $context['json_decode_options']; if (version_compare(PHP_VERSION, '5.4.0') >= 0) { $decodedData = json_decode($data, $associative, $recursionDepth, $options); } else { $decodedData = json_decode($data, $associative, $recursionDepth); } $this->lastError = json_last_error(); return $decodedData; } /** * {@inheritdoc} */ public function supportsDecoding($format) { return JsonEncoder::FORMAT === $format; } /** * Merges the default options of the Json Decoder with the passed context. * * @param array $context * * @return array */ private function resolveContext(array $context) { $defaultOptions = array( 'json_decode_associative' => $this->associative, 'json_decode_recursion_depth' => $this->recursionDepth, 'json_decode_options' => 0 ); return array_merge($defaultOptions, $context); } } PK] ovv"Serializer/Encoder/JsonEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Encodes JSON data * * @author Jordi Boggiano */ class JsonEncoder implements EncoderInterface, DecoderInterface { const FORMAT = 'json'; /** * @var JsonEncode */ protected $encodingImpl; /** * @var JsonDecode */ protected $decodingImpl; public function __construct(JsonEncode $encodingImpl = null, JsonDecode $decodingImpl = null) { $this->encodingImpl = $encodingImpl ?: new JsonEncode(); $this->decodingImpl = $decodingImpl ?: new JsonDecode(true); } /** * Returns the last encoding error (if any) * * @return integer */ public function getLastEncodingError() { return $this->encodingImpl->getLastError(); } /** * Returns the last decoding error (if any) * * @return integer */ public function getLastDecodingError() { return $this->decodingImpl->getLastError(); } /** * {@inheritdoc} */ public function encode($data, $format, array $context = array()) { return $this->encodingImpl->encode($data, self::FORMAT, $context); } /** * {@inheritdoc} */ public function decode($data, $format, array $context = array()) { return $this->decodingImpl->decode($data, self::FORMAT, $context); } /** * {@inheritdoc} */ public function supportsEncoding($format) { return self::FORMAT === $format; } /** * {@inheritdoc} */ public function supportsDecoding($format) { return self::FORMAT === $format; } } PK]=-Serializer/Encoder/SerializerAwareEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\SerializerAwareInterface; /** * SerializerAware Encoder implementation * * @author Jordi Boggiano */ abstract class SerializerAwareEncoder implements SerializerAwareInterface { protected $serializer; /** * {@inheritdoc} */ public function setSerializer(SerializerInterface $serializer) { $this->serializer = $serializer; } } PK]|ͼ'Serializer/Encoder/DecoderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Defines the interface of decoders * * @author Jordi Boggiano */ interface DecoderInterface { /** * Decodes a string into PHP data. * * @param scalar $data Data to decode * @param string $format Format name * @param array $context options that decoders have access to. * * The format parameter specifies which format the data is in; valid values * depend on the specific implementation. Authors implementing this interface * are encouraged to document which formats they support in a non-inherited * phpdoc comment. * * @return mixed */ public function decode($data, $format, array $context = array()); /** * Checks whether the deserializer can decode from given format. * * @param string $format format name * * @return Boolean */ public function supportsDecoding($format); } PK]v:hh!Serializer/Encoder/JsonEncode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Encodes JSON data * * @author Sander Coolen */ class JsonEncode implements EncoderInterface { private $options ; private $lastError = JSON_ERROR_NONE; public function __construct($bitmask = 0) { $this->options = $bitmask; } /** * Returns the last encoding error (if any) * * @return integer * * @see http://php.net/manual/en/function.json-last-error.php json_last_error */ public function getLastError() { return $this->lastError; } /** * Encodes PHP data to a JSON string * * {@inheritdoc} */ public function encode($data, $format, array $context = array()) { $context = $this->resolveContext($context); $encodedJson = json_encode($data, $context['json_encode_options']); $this->lastError = json_last_error(); return $encodedJson; } /** * {@inheritdoc} */ public function supportsEncoding($format) { return JsonEncoder::FORMAT === $format; } /** * Merge default json encode options with context. * * @param array $context * @return array */ private function resolveContext(array $context = array()) { return array_merge(array('json_encode_options' => $this->options), $context); } } PK],c'Serializer/Encoder/EncoderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Defines the interface of encoders * * @author Jordi Boggiano */ interface EncoderInterface { /** * Encodes data into the given format * * @param mixed $data Data to encode * @param string $format Format name * @param array $context options that normalizers/encoders have access to. * * @return scalar */ public function encode($data, $format, array $context = array()); /** * Checks whether the serializer can encode to given format * * @param string $format format name * * @return Boolean */ public function supportsEncoding($format); } PK]<=gg2Serializer/Encoder/NormalizationAwareInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Defines the interface of encoders that will normalize data themselves * * Implementing this interface essentially just tells the Serializer that the * data should not be pre-normalized before being passed to this Encoder. * * @author Jordi Boggiano */ interface NormalizationAwareInterface { } PK]x蕰  "Serializer/SerializerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer; /** * Defines the interface of the Serializer * * @author Jordi Boggiano */ interface SerializerInterface { /** * Serializes data in the appropriate format * * @param mixed $data any data * @param string $format format name * @param array $context options normalizers/encoders have access to * * @return string */ public function serialize($data, $format, array $context = array()); /** * Deserializes data into the given type. * * @param mixed $data * @param string $type * @param string $format * @param array $context * * @return object */ public function deserialize($data, $type, $format, array $context = array()); } PK]TTSerializer/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale; use Symfony\Component\Icu\IcuData; use Symfony\Component\Intl\Intl; /** * Helper class for dealing with locale strings. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Locale} and {@link \Symfony\Component\Intl\Intl} instead. */ class Locale extends \Locale { /** * Caches the countries in different locales * @var array */ protected static $countries = array(); /** * Caches the languages in different locales * @var array */ protected static $languages = array(); /** * Caches the different locales * @var array */ protected static $locales = array(); /** * Returns the country names for a locale * * @param string $locale The locale to use for the country names * * @return array The country names with their codes as keys * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getDisplayCountries($locale) { if (!isset(self::$countries[$locale])) { self::$countries[$locale] = Intl::getRegionBundle()->getCountryNames($locale); } return self::$countries[$locale]; } /** * Returns all available country codes * * @return array The country codes * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getCountries() { return array_keys(self::getDisplayCountries(self::getDefault())); } /** * Returns the language names for a locale * * @param string $locale The locale to use for the language names * * @return array The language names with their codes as keys * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getDisplayLanguages($locale) { if (!isset(self::$languages[$locale])) { self::$languages[$locale] = Intl::getLanguageBundle()->getLanguageNames($locale); } return self::$languages[$locale]; } /** * Returns all available language codes * * @return array The language codes * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getLanguages() { return array_keys(self::getDisplayLanguages(self::getDefault())); } /** * Returns the locale names for a locale * * @param string $locale The locale to use for the locale names * * @return array The locale names with their codes as keys * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getDisplayLocales($locale) { if (!isset(self::$locales[$locale])) { self::$locales[$locale] = Intl::getLocaleBundle()->getLocaleNames($locale); } return self::$locales[$locale]; } /** * Returns all available locale codes * * @return array The locale codes * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getLocales() { return array_keys(self::getDisplayLocales(self::getDefault())); } /** * Returns the ICU version as defined by the intl extension * * @return string|null The ICU version */ public static function getIntlIcuVersion() { return Intl::getIcuVersion(); } /** * Returns the ICU Data version as defined by the intl extension * * @return string|null The ICU Data version */ public static function getIntlIcuDataVersion() { return Intl::getIcuDataVersion(); } /** * Returns the ICU data version that ships with Symfony. If the environment variable USE_INTL_ICU_DATA_VERSION is * defined, it will try use the ICU data version as defined by the intl extension, if available. * * @return string The ICU data version that ships with Symfony */ public static function getIcuDataVersion() { return Intl::getIcuDataVersion(); } /** * Returns the directory path of the ICU data that ships with Symfony * * @return string The path to the ICU data directory */ public static function getIcuDataDirectory() { return IcuData::getResourceDirectory(); } /** * Returns the fallback locale for a given locale, if any * * @param string $locale The locale to find the fallback for. * * @return string|null The fallback locale, or null if no parent exists */ protected static function getFallbackLocale($locale) { if (false === $pos = strrpos($locale, '_')) { return null; } return substr($locale, 0, $pos); } } PK]S?a%%2Locale/Exception/MethodNotImplementedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Exception; use Symfony\Component\Intl\Exception\MethodNotImplementedException as BaseMethodNotImplementedException; /** * Alias of {@link \Symfony\Component\Intl\Exception\MethodNotImplementedException}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Exception\MethodNotImplementedException} * instead. */ class MethodNotImplementedException extends BaseMethodNotImplementedException { } PK] E,Locale/Exception/NotImplementedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Exception; use Symfony\Component\Intl\Exception\NotImplementedException as BaseNotImplementedException; /** * Alias of {@link \Symfony\Component\Intl\Exception\NotImplementedException}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Exception\NotImplementedException} * instead. */ class NotImplementedException extends BaseNotImplementedException { } PK]ss?Locale/Exception/MethodArgumentValueNotImplementedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Exception; use Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException as BaseMethodArgumentValueNotImplementedException; /** * Alias of {@link \Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException} * instead. */ class MethodArgumentValueNotImplementedException extends BaseMethodArgumentValueNotImplementedException { } PK]QUU:Locale/Exception/MethodArgumentNotImplementedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Exception; use Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException as BaseMethodArgumentNotImplementedException; /** * Alias of {@link \Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException} * instead. */ class MethodArgumentNotImplementedException extends BaseMethodArgumentNotImplementedException { } PK] S%Locale/Stub/StubIntlDateFormatter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub; use Symfony\Component\Intl\DateFormatter\IntlDateFormatter; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\IntlDateFormatter}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\IntlDateFormatter} * instead. */ class StubIntlDateFormatter extends IntlDateFormatter { } PK])Locale/Stub/DateFormat/DayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\DayTransformer as BaseDayTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayTransformer} * instead. */ class DayTransformer extends BaseDayTransformer { } PK]   *Locale/Stub/DateFormat/HourTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\HourTransformer as BaseHourTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\HourTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\HourTransformer} * instead. */ abstract class HourTransformer extends BaseHourTransformer { } PK]Ed&Locale/Stub/DateFormat/Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\Transformer as BaseTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Transformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Transformer} * instead. */ abstract class Transformer extends BaseTransformer { } PK]v/.Locale/Stub/DateFormat/Hour2401Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\Hour2401Transformer as BaseHour2401Transformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2401Transformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2401Transformer} * instead. */ class Hour2401Transformer extends BaseHour2401Transformer { } PK]mў-Locale/Stub/DateFormat/QuarterTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\QuarterTransformer as BaseQuarterTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\QuarterTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\QuarterTransformer} * instead. */ class QuarterTransformer extends BaseQuarterTransformer { } PK]3X,Locale/Stub/DateFormat/SecondTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\SecondTransformer as BaseSecondTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\SecondTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\SecondTransformer} * instead. */ class SecondTransformer extends BaseSecondTransformer { } PK]g[ep,Locale/Stub/DateFormat/MinuteTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\MinuteTransformer as BaseMinuteTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MinuteTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MinuteTransformer} * instead. */ class MinuteTransformer extends BaseMinuteTransformer { } PK]kH*Locale/Stub/DateFormat/FullTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\FullTransformer as BaseFullTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\FullTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\FullTransformer} * instead. */ class FullTransformer extends BaseFullTransformer { } PK]*Locale/Stub/DateFormat/YearTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\YearTransformer as BaseYearTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\YearTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\YearTransformer} * instead. */ class YearTransformer extends BaseYearTransformer { } PK]:6""/Locale/Stub/DateFormat/DayOfWeekTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\DayOfWeekTransformer as BaseDayOfWeekTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfWeekTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfWeekTransformer} * instead. */ class DayOfWeekTransformer extends BaseDayOfWeekTransformer { } PK]} ""/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\DayOfYearTransformer as BaseDayOfYearTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfYearTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfYearTransformer} * instead. */ class DayOfYearTransformer extends BaseDayOfYearTransformer { } PK] 9u.Locale/Stub/DateFormat/Hour1200Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\Hour1200Transformer as BaseHour1200Transformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1200Transformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1200Transformer} * instead. */ class Hour1200Transformer extends BaseHour1200Transformer { } PK]k&"M.Locale/Stub/DateFormat/Hour1201Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\Hour1201Transformer as BaseHour1201Transformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1201Transformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1201Transformer} * instead. */ class Hour1201Transformer extends BaseHour1201Transformer { } PK]S.Locale/Stub/DateFormat/TimeZoneTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\TimeZoneTransformer as BaseTimeZoneTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\TimeZoneTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\TimeZoneTransformer} * instead. */ class TimeZoneTransformer extends BaseTimeZoneTransformer { } PK]tz  +Locale/Stub/DateFormat/MonthTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\MonthTransformer as BaseMonthTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MonthTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MonthTransformer} * instead. */ class MonthTransformer extends BaseMonthTransformer { } PK].Locale/Stub/DateFormat/Hour2400Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\Hour2400Transformer as BaseHour2400Transformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2400Transformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2400Transformer} * instead. */ class Hour2400Transformer extends BaseHour2400Transformer { } PK]X*Locale/Stub/DateFormat/AmPmTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\AmPmTransformer as BaseAmPmTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\AmPmTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\AmPmTransformer} * instead. */ class AmPmTransformer extends BaseAmPmTransformer { } PK]&#Locale/Stub/StubNumberFormatter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub; use Symfony\Component\Intl\NumberFormatter\NumberFormatter; /** * Alias of {@link \Symfony\Component\Intl\NumberFormatter\NumberFormatter}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\NumberFormatter\NumberFormatter} * instead. */ class StubNumberFormatter extends NumberFormatter { } PK]CLocale/Stub/StubIntl.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub; use Symfony\Component\Intl\Globals\IntlGlobals; /** * Alias of {@link \Symfony\Component\Intl\Globals\IntlGlobals}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Globals\IntlGlobals} instead. */ abstract class StubIntl extends IntlGlobals { } PK]?Locale/Stub/StubCollator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub; use Symfony\Component\Intl\Collator\Collator; /** * Alias of {@link \Symfony\Component\Intl\Collator\Collator}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Collator\Collator} instead. */ class StubCollator extends Collator { } PK]q*( ( Locale/Stub/StubLocale.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub; use Symfony\Component\Icu\IcuData; use Symfony\Component\Intl\Intl; use Symfony\Component\Intl\Locale\Locale; /** * Alias of {@link \Symfony\Component\Intl\Locale\Locale}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Locale\Locale} and * {@link \Symfony\Component\Intl\Intl} instead. */ class StubLocale extends Locale { /** * Caches the currencies * * @var array */ protected static $currencies; /** * Caches the currencies names * * @var array */ protected static $currenciesNames; /** * Returns the currencies data * * @param string $locale * * @return array The currencies data */ public static function getCurrenciesData($locale) { if (null === self::$currencies) { self::prepareCurrencies($locale); } return self::$currencies; } /** * Returns the currencies names for a locale * * @param string $locale The locale to use for the currencies names * * @return array The currencies names with their codes as keys * * @throws \InvalidArgumentException When the locale is different than 'en' */ public static function getDisplayCurrencies($locale) { if (null === self::$currenciesNames) { self::prepareCurrencies($locale); } return self::$currenciesNames; } /** * Returns all available currencies codes * * @return array The currencies codes */ public static function getCurrencies() { return array_keys(self::getCurrenciesData(self::getDefault())); } public static function getDataDirectory() { return IcuData::getResourceDirectory(); } private static function prepareCurrencies($locale) { self::$currencies = array(); self::$currenciesNames = array(); $bundle = Intl::getCurrencyBundle(); foreach ($bundle->getCurrencyNames($locale) as $currency => $name) { self::$currencies[$currency] = array( 'name' => $name, 'symbol' => $bundle->getCurrencySymbol($currency, $locale), 'fractionDigits' => $bundle->getFractionDigits($currency), 'roundingIncrement' => $bundle->getRoundingIncrement($currency) ); self::$currenciesNames[$currency] = $name; } } } PK]FPPPLocale/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem\Exception; /** * Exception interface for all exceptions thrown by the component. * * @author Romain Neutron * * @api */ interface ExceptionInterface { } PK];{$Filesystem/Exception/IOException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem\Exception; /** * Exception class thrown when a filesystem operation failure happens * * @author Romain Neutron * @author Christian Gärtner * @author Fabien Potencier * * @api */ class IOException extends \RuntimeException implements IOExceptionInterface { private $path; public function __construct($message, $code = 0, \Exception $previous = null, $path = null) { $this->path = $path; parent::__construct($message, $code, $previous); } /** * {@inheritdoc} */ public function getPath() { return $this->path; } } PK]dP.Filesystem/Exception/FileNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem\Exception; /** * Exception class thrown when a file couldn't be found * * @author Fabien Potencier * @author Christian Gärtner */ class FileNotFoundException extends IOException { public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null) { if (null === $message) { if (null === $path) { $message = 'File could not be found.'; } else { $message = sprintf('File "%s" could not be found.', $path); } } parent::__construct($message, $code, $previous, $path); } } PK]oC~-Filesystem/Exception/IOExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem\Exception; /** * IOException interface for file and input/output stream related exceptions thrown by the component. * * @author Christian Gärtner */ interface IOExceptionInterface extends ExceptionInterface { /** * Returns the associated path for the exception * * @return string The path. */ public function getPath(); } PK]tTTFilesystem/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Exception\FileNotFoundException; /** * Provides basic utility to manipulate the file system. * * @author Fabien Potencier */ class Filesystem { /** * Copies a file. * * This method only copies the file if the origin file is newer than the target file. * * By default, if the target already exists, it is not overridden. * * @param string $originFile The original filename * @param string $targetFile The target filename * @param boolean $override Whether to override an existing file or not * * @throws FileNotFoundException When originFile doesn't exist * @throws IOException When copy fails */ public function copy($originFile, $targetFile, $override = false) { if (stream_is_local($originFile) && !is_file($originFile)) { throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile); } $this->mkdir(dirname($targetFile)); if (!$override && is_file($targetFile) && null === parse_url($originFile, PHP_URL_HOST)) { $doCopy = filemtime($originFile) > filemtime($targetFile); } else { $doCopy = true; } if ($doCopy) { // https://bugs.php.net/bug.php?id=64634 $source = fopen($originFile, 'r'); $target = fopen($targetFile, 'w'); stream_copy_to_stream($source, $target); fclose($source); fclose($target); unset($source, $target); if (!is_file($targetFile)) { throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile); } } } /** * Creates a directory recursively. * * @param string|array|\Traversable $dirs The directory path * @param integer $mode The directory mode * * @throws IOException On any directory creation failure */ public function mkdir($dirs, $mode = 0777) { foreach ($this->toIterator($dirs) as $dir) { if (is_dir($dir)) { continue; } if (true !== @mkdir($dir, $mode, true)) { throw new IOException(sprintf('Failed to create "%s".', $dir), 0, null, $dir); } } } /** * Checks the existence of files or directories. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to check * * @return Boolean true if the file exists, false otherwise */ public function exists($files) { foreach ($this->toIterator($files) as $file) { if (!file_exists($file)) { return false; } } return true; } /** * Sets access and modification time of file. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create * @param integer $time The touch time as a Unix timestamp * @param integer $atime The access time as a Unix timestamp * * @throws IOException When touch fails */ public function touch($files, $time = null, $atime = null) { foreach ($this->toIterator($files) as $file) { $touch = $time ? @touch($file, $time, $atime) : @touch($file); if (true !== $touch) { throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file); } } } /** * Removes files or directories. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove * * @throws IOException When removal fails */ public function remove($files) { $files = iterator_to_array($this->toIterator($files)); $files = array_reverse($files); foreach ($files as $file) { if (!file_exists($file) && !is_link($file)) { continue; } if (is_dir($file) && !is_link($file)) { $this->remove(new \FilesystemIterator($file)); if (true !== @rmdir($file)) { throw new IOException(sprintf('Failed to remove directory "%s".', $file), 0, null, $file); } } else { // https://bugs.php.net/bug.php?id=52176 if (defined('PHP_WINDOWS_VERSION_MAJOR') && is_dir($file)) { if (true !== @rmdir($file)) { throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file); } } else { if (true !== @unlink($file)) { throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file); } } } } } /** * Change mode for an array of files or directories. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change mode * @param integer $mode The new mode (octal) * @param integer $umask The mode mask (octal) * @param Boolean $recursive Whether change the mod recursively or not * * @throws IOException When the change fail */ public function chmod($files, $mode, $umask = 0000, $recursive = false) { foreach ($this->toIterator($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { $this->chmod(new \FilesystemIterator($file), $mode, $umask, true); } if (true !== @chmod($file, $mode & ~$umask)) { throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file); } } } /** * Change the owner of an array of files or directories * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change owner * @param string $user The new owner user name * @param Boolean $recursive Whether change the owner recursively or not * * @throws IOException When the change fail */ public function chown($files, $user, $recursive = false) { foreach ($this->toIterator($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { $this->chown(new \FilesystemIterator($file), $user, true); } if (is_link($file) && function_exists('lchown')) { if (true !== @lchown($file, $user)) { throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); } } else { if (true !== @chown($file, $user)) { throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); } } } } /** * Change the group of an array of files or directories * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change group * @param string $group The group name * @param Boolean $recursive Whether change the group recursively or not * * @throws IOException When the change fail */ public function chgrp($files, $group, $recursive = false) { foreach ($this->toIterator($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { $this->chgrp(new \FilesystemIterator($file), $group, true); } if (is_link($file) && function_exists('lchgrp')) { if (true !== @lchgrp($file, $group)) { throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); } } else { if (true !== @chgrp($file, $group)) { throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); } } } } /** * Renames a file or a directory. * * @param string $origin The origin filename or directory * @param string $target The new filename or directory * @param Boolean $overwrite Whether to overwrite the target if it already exists * * @throws IOException When target file or directory already exists * @throws IOException When origin cannot be renamed */ public function rename($origin, $target, $overwrite = false) { // we check that target does not exist if (!$overwrite && is_readable($target)) { throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target); } if (true !== @rename($origin, $target)) { throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target); } } /** * Creates a symbolic link or copy a directory. * * @param string $originDir The origin directory path * @param string $targetDir The symbolic link name * @param Boolean $copyOnWindows Whether to copy files if on Windows * * @throws IOException When symlink fails */ public function symlink($originDir, $targetDir, $copyOnWindows = false) { if (!function_exists('symlink') && $copyOnWindows) { $this->mirror($originDir, $targetDir); return; } $this->mkdir(dirname($targetDir)); $ok = false; if (is_link($targetDir)) { if (readlink($targetDir) != $originDir) { $this->remove($targetDir); } else { $ok = true; } } if (!$ok) { if (true !== @symlink($originDir, $targetDir)) { $report = error_get_last(); if (is_array($report)) { if (defined('PHP_WINDOWS_VERSION_MAJOR') && false !== strpos($report['message'], 'error code(1314)')) { throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?'); } } throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir); } } } /** * Given an existing path, convert it to a path relative to a given starting path * * @param string $endPath Absolute path of target * @param string $startPath Absolute path where traversal begins * * @return string Path of target relative to starting path */ public function makePathRelative($endPath, $startPath) { // Normalize separators on Windows if (defined('PHP_WINDOWS_VERSION_MAJOR')) { $endPath = strtr($endPath, '\\', '/'); $startPath = strtr($startPath, '\\', '/'); } // Split the paths into arrays $startPathArr = explode('/', trim($startPath, '/')); $endPathArr = explode('/', trim($endPath, '/')); // Find for which directory the common path stops $index = 0; while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) { $index++; } // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels) $depth = count($startPathArr) - $index; // Repeated "../" for each level need to reach the common path $traverser = str_repeat('../', $depth); $endPathRemainder = implode('/', array_slice($endPathArr, $index)); // Construct $endPath from traversing to the common path, then to the remaining $endPath $relativePath = $traverser.(strlen($endPathRemainder) > 0 ? $endPathRemainder.'/' : ''); return (strlen($relativePath) === 0) ? './' : $relativePath; } /** * Mirrors a directory to another. * * @param string $originDir The origin directory * @param string $targetDir The target directory * @param \Traversable $iterator A Traversable instance * @param array $options An array of boolean options * Valid options are: * - $options['override'] Whether to override an existing file on copy or not (see copy()) * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink()) * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) * * @throws IOException When file type is unknown */ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array()) { $targetDir = rtrim($targetDir, '/\\'); $originDir = rtrim($originDir, '/\\'); // Iterate in destination folder to remove obsolete entries if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) { $deleteIterator = $iterator; if (null === $deleteIterator) { $flags = \FilesystemIterator::SKIP_DOTS; $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST); } foreach ($deleteIterator as $file) { $origin = str_replace($targetDir, $originDir, $file->getPathname()); if (!$this->exists($origin)) { $this->remove($file); } } } $copyOnWindows = false; if (isset($options['copy_on_windows']) && !function_exists('symlink')) { $copyOnWindows = $options['copy_on_windows']; } if (null === $iterator) { $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS; $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST); } foreach ($iterator as $file) { $target = str_replace($originDir, $targetDir, $file->getPathname()); if ($copyOnWindows) { if (is_link($file) || is_file($file)) { $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); } elseif (is_dir($file)) { $this->mkdir($target); } else { throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); } } else { if (is_link($file)) { $this->symlink($file->getLinkTarget(), $target); } elseif (is_dir($file)) { $this->mkdir($target); } elseif (is_file($file)) { $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); } else { throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); } } } } /** * Returns whether the file path is an absolute path. * * @param string $file A file path * * @return Boolean */ public function isAbsolutePath($file) { if (strspn($file, '/\\', 0, 1) || (strlen($file) > 3 && ctype_alpha($file[0]) && substr($file, 1, 1) === ':' && (strspn($file, '/\\', 2, 1)) ) || null !== parse_url($file, PHP_URL_SCHEME) ) { return true; } return false; } /** * Atomically dumps content into a file. * * @param string $filename The file to be written to. * @param string $content The data to write into the file. * @param null|integer $mode The file mode (octal). If null, file permissions are not modified * Deprecated since version 2.3.12, to be removed in 3.0. * @throws IOException If the file cannot be written to. */ public function dumpFile($filename, $content, $mode = 0666) { $dir = dirname($filename); if (!is_dir($dir)) { $this->mkdir($dir); } elseif (!is_writable($dir)) { throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); } $tmpFile = tempnam($dir, basename($filename)); if (false === @file_put_contents($tmpFile, $content)) { throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); } $this->rename($tmpFile, $filename, true); if (null !== $mode) { $this->chmod($filename, $mode); } } /** * @param mixed $files * * @return \Traversable */ private function toIterator($files) { if (!$files instanceof \Traversable) { $files = new \ArrayObject(is_array($files) ? $files : array($files)); } return $files; } } PK]I Config/FileLocator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config; /** * FileLocator uses an array of pre-defined paths to find files. * * @author Fabien Potencier */ class FileLocator implements FileLocatorInterface { protected $paths; /** * Constructor. * * @param string|array $paths A path or an array of paths where to look for resources */ public function __construct($paths = array()) { $this->paths = (array) $paths; } /** * Returns a full path for a given file name. * * @param mixed $name The file name to locate * @param string $currentPath The current path * @param Boolean $first Whether to return the first occurrence or an array of filenames * * @return string|array The full path to the file|An array of file paths * * @throws \InvalidArgumentException When file is not found */ public function locate($name, $currentPath = null, $first = true) { if ($this->isAbsolutePath($name)) { if (!file_exists($name)) { throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $name)); } return $name; } $filepaths = array(); if (null !== $currentPath && file_exists($file = $currentPath.DIRECTORY_SEPARATOR.$name)) { if (true === $first) { return $file; } $filepaths[] = $file; } foreach ($this->paths as $path) { if (file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) { if (true === $first) { return $file; } $filepaths[] = $file; } } if (!$filepaths) { throw new \InvalidArgumentException(sprintf('The file "%s" does not exist (in: %s%s).', $name, null !== $currentPath ? $currentPath.', ' : '', implode(', ', $this->paths))); } return array_values(array_unique($filepaths)); } /** * Returns whether the file path is an absolute path. * * @param string $file A file path * * @return Boolean */ private function isAbsolutePath($file) { if ($file[0] == '/' || $file[0] == '\\' || (strlen($file) > 3 && ctype_alpha($file[0]) && $file[1] == ':' && ($file[2] == '\\' || $file[2] == '/') ) || null !== parse_url($file, PHP_URL_SCHEME) ) { return true; } return false; } } PK]C3kllConfig/FileLocatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config; /** * @author Fabien Potencier */ interface FileLocatorInterface { /** * Returns a full path for a given file name. * * @param mixed $name The file name to locate * @param string $currentPath The current path * @param Boolean $first Whether to return the first occurrence or an array of filenames * * @return string|array The full path to the file|An array of file paths * * @throws \InvalidArgumentException When file is not found */ public function locate($name, $currentPath = null, $first = true); } PK]kConfig/Util/XmlUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Util; /** * XMLUtils is a bunch of utility methods to XML operations. * * This class contains static methods only and is not meant to be instantiated. * * @author Fabien Potencier * @author Martin Hasoň */ class XmlUtils { /** * This class should not be instantiated */ private function __construct() { } /** * Loads an XML file. * * @param string $file An XML file path * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation * * @return \DOMDocument * * @throws \InvalidArgumentException When loading of XML file returns error */ public static function loadFile($file, $schemaOrCallable = null) { $content = @file_get_contents($file); if ('' === trim($content)) { throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file)); } $internalErrors = libxml_use_internal_errors(true); $disableEntities = libxml_disable_entity_loader(true); libxml_clear_errors(); $dom = new \DOMDocument(); $dom->validateOnParse = true; if (!$dom->loadXML($content, LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) { libxml_disable_entity_loader($disableEntities); throw new \InvalidArgumentException(implode("\n", static::getXmlErrors($internalErrors))); } $dom->normalizeDocument(); libxml_use_internal_errors($internalErrors); libxml_disable_entity_loader($disableEntities); foreach ($dom->childNodes as $child) { if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { throw new \InvalidArgumentException('Document types are not allowed.'); } } if (null !== $schemaOrCallable) { $internalErrors = libxml_use_internal_errors(true); libxml_clear_errors(); $e = null; if (is_callable($schemaOrCallable)) { try { $valid = call_user_func($schemaOrCallable, $dom, $internalErrors); } catch (\Exception $e) { $valid = false; } } elseif (!is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) { $valid = @$dom->schemaValidate($schemaOrCallable); } else { libxml_use_internal_errors($internalErrors); throw new \InvalidArgumentException('The schemaOrCallable argument has to be a valid path to XSD file or callable.'); } if (!$valid) { $messages = static::getXmlErrors($internalErrors); if (empty($messages)) { $messages = array(sprintf('The XML file "%s" is not valid.', $file)); } throw new \InvalidArgumentException(implode("\n", $messages), 0, $e); } libxml_use_internal_errors($internalErrors); } return $dom; } /** * Converts a \DomElement object to a PHP array. * * The following rules applies during the conversion: * * * Each tag is converted to a key value or an array * if there is more than one "value" * * * The content of a tag is set under a "value" key (bar) * if the tag also has some nested tags * * * The attributes are converted to keys () * * * The nested-tags are converted to keys (bar) * * @param \DomElement $element A \DomElement instance * @param Boolean $checkPrefix Check prefix in an element or an attribute name * * @return array A PHP array */ public static function convertDomElementToArray(\DomElement $element, $checkPrefix = true) { $prefix = (string) $element->prefix; $empty = true; $config = array(); foreach ($element->attributes as $name => $node) { if ($checkPrefix && !in_array((string) $node->prefix, array('', $prefix), true)) { continue; } $config[$name] = static::phpize($node->value); $empty = false; } $nodeValue = false; foreach ($element->childNodes as $node) { if ($node instanceof \DOMText) { if ('' !== trim($node->nodeValue)) { $nodeValue = trim($node->nodeValue); $empty = false; } } elseif ($checkPrefix && $prefix != (string) $node->prefix) { continue; } elseif (!$node instanceof \DOMComment) { $value = static::convertDomElementToArray($node, $checkPrefix); $key = $node->localName; if (isset($config[$key])) { if (!is_array($config[$key]) || !is_int(key($config[$key]))) { $config[$key] = array($config[$key]); } $config[$key][] = $value; } else { $config[$key] = $value; } $empty = false; } } if (false !== $nodeValue) { $value = static::phpize($nodeValue); if (count($config)) { $config['value'] = $value; } else { $config = $value; } } return !$empty ? $config : null; } /** * Converts an xml value to a PHP type. * * @param mixed $value * * @return mixed */ public static function phpize($value) { $value = (string) $value; $lowercaseValue = strtolower($value); switch (true) { case 'null' === $lowercaseValue: return null; case ctype_digit($value): $raw = $value; $cast = intval($value); return '0' == $value[0] ? octdec($value) : (((string) $raw == (string) $cast) ? $cast : $raw); case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)): $raw = $value; $cast = intval($value); return '0' == $value[1] ? octdec($value) : (((string) $raw == (string) $cast) ? $cast : $raw); case 'true' === $lowercaseValue: return true; case 'false' === $lowercaseValue: return false; case isset($value[1]) && '0b' == $value[0].$value[1]: return bindec($value); case is_numeric($value): return '0x' == $value[0].$value[1] ? hexdec($value) : floatval($value); case preg_match('/^(-|\+)?[0-9]+(\.[0-9]+)?$/', $value): return floatval($value); default: return $value; } } protected static function getXmlErrors($internalErrors) { $errors = array(); foreach (libxml_get_errors() as $error) { $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', $error->code, trim($error->message), $error->file ? $error->file : 'n/a', $error->line, $error->column ); } libxml_clear_errors(); libxml_use_internal_errors($internalErrors); return $errors; } } PK]B""Config/Definition/BaseNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\Exception; use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; /** * The base node class * * @author Johannes M. Schmitt */ abstract class BaseNode implements NodeInterface { protected $name; protected $parent; protected $normalizationClosures = array(); protected $finalValidationClosures = array(); protected $allowOverwrite = true; protected $required = false; protected $equivalentValues = array(); protected $attributes = array(); /** * Constructor. * * @param string $name The name of the node * @param NodeInterface $parent The parent of this node * * @throws \InvalidArgumentException if the name contains a period. */ public function __construct($name, NodeInterface $parent = null) { if (false !== strpos($name, '.')) { throw new \InvalidArgumentException('The name must not contain ".".'); } $this->name = $name; $this->parent = $parent; } public function setAttribute($key, $value) { $this->attributes[$key] = $value; } public function getAttribute($key, $default = null) { return isset($this->attributes[$key]) ? $this->attributes[$key] : $default; } public function hasAttribute($key) { return isset($this->attributes[$key]); } public function getAttributes() { return $this->attributes; } public function setAttributes(array $attributes) { $this->attributes = $attributes; } public function removeAttribute($key) { unset($this->attributes[$key]); } /** * Sets an info message. * * @param string $info */ public function setInfo($info) { $this->setAttribute('info', $info); } /** * Returns info message. * * @return string The info text */ public function getInfo() { return $this->getAttribute('info'); } /** * Sets the example configuration for this node. * * @param string|array $example */ public function setExample($example) { $this->setAttribute('example', $example); } /** * Retrieves the example configuration for this node. * * @return string|array The example */ public function getExample() { return $this->getAttribute('example'); } /** * Adds an equivalent value. * * @param mixed $originalValue * @param mixed $equivalentValue */ public function addEquivalentValue($originalValue, $equivalentValue) { $this->equivalentValues[] = array($originalValue, $equivalentValue); } /** * Set this node as required. * * @param Boolean $boolean Required node */ public function setRequired($boolean) { $this->required = (Boolean) $boolean; } /** * Sets if this node can be overridden. * * @param Boolean $allow */ public function setAllowOverwrite($allow) { $this->allowOverwrite = (Boolean) $allow; } /** * Sets the closures used for normalization. * * @param \Closure[] $closures An array of Closures used for normalization */ public function setNormalizationClosures(array $closures) { $this->normalizationClosures = $closures; } /** * Sets the closures used for final validation. * * @param \Closure[] $closures An array of Closures used for final validation */ public function setFinalValidationClosures(array $closures) { $this->finalValidationClosures = $closures; } /** * Checks if this node is required. * * @return Boolean */ public function isRequired() { return $this->required; } /** * Returns the name of this node * * @return string The Node's name. */ public function getName() { return $this->name; } /** * Retrieves the path of this node. * * @return string The Node's path */ public function getPath() { $path = $this->name; if (null !== $this->parent) { $path = $this->parent->getPath().'.'.$path; } return $path; } /** * Merges two values together. * * @param mixed $leftSide * @param mixed $rightSide * * @return mixed The merged value * * @throws ForbiddenOverwriteException */ final public function merge($leftSide, $rightSide) { if (!$this->allowOverwrite) { throw new ForbiddenOverwriteException(sprintf( 'Configuration path "%s" cannot be overwritten. You have to ' .'define all options for this path, and any of its sub-paths in ' .'one configuration section.', $this->getPath() )); } $this->validateType($leftSide); $this->validateType($rightSide); return $this->mergeValues($leftSide, $rightSide); } /** * Normalizes a value, applying all normalization closures. * * @param mixed $value Value to normalize. * * @return mixed The normalized value. */ final public function normalize($value) { $value = $this->preNormalize($value); // run custom normalization closures foreach ($this->normalizationClosures as $closure) { $value = $closure($value); } // replace value with their equivalent foreach ($this->equivalentValues as $data) { if ($data[0] === $value) { $value = $data[1]; } } // validate type $this->validateType($value); // normalize value return $this->normalizeValue($value); } /** * Normalizes the value before any other normalization is applied. * * @param $value * * @return $value The normalized array value */ protected function preNormalize($value) { return $value; } /** * Returns parent node for this node. * * @return NodeInterface|null */ public function getParent() { return $this->parent; } /** * Finalizes a value, applying all finalization closures. * * @param mixed $value The value to finalize * * @return mixed The finalized value * * @throws InvalidConfigurationException */ final public function finalize($value) { $this->validateType($value); $value = $this->finalizeValue($value); // Perform validation on the final value if a closure has been set. // The closure is also allowed to return another value. foreach ($this->finalValidationClosures as $closure) { try { $value = $closure($value); } catch (Exception $correctEx) { throw $correctEx; } catch (\Exception $invalid) { throw new InvalidConfigurationException(sprintf( 'Invalid configuration for path "%s": %s', $this->getPath(), $invalid->getMessage() ), $invalid->getCode(), $invalid); } } return $value; } /** * Validates the type of a Node. * * @param mixed $value The value to validate * * @throws InvalidTypeException when the value is invalid */ abstract protected function validateType($value); /** * Normalizes the value. * * @param mixed $value The value to normalize. * * @return mixed The normalized value */ abstract protected function normalizeValue($value); /** * Merges two values together. * * @param mixed $leftSide * @param mixed $rightSide * * @return mixed The merged value */ abstract protected function mergeValues($leftSide, $rightSide); /** * Finalizes a value. * * @param mixed $value The value to finalize * * @return mixed The finalized value */ abstract protected function finalizeValue($value); } PK]eww,Config/Definition/PrototypeNodeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * This interface must be implemented by nodes which can be used as prototypes. * * @author Johannes M. Schmitt */ interface PrototypeNodeInterface extends NodeInterface { /** * Sets the name of the node. * * @param string $name The name of the node */ public function setName($name); } PK]jkk!Config/Definition/IntegerNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents an integer value in the config tree. * * @author Jeanmonod David */ class IntegerNode extends NumericNode { /** * {@inheritDoc} */ protected function validateType($value) { if (!is_int($value)) { $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected int, but got %s.', $this->getPath(), gettype($value))); $ex->setPath($this->getPath()); throw $ex; } } } PK]+;; Config/Definition/ScalarNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents a scalar value in the config tree. * * The following values are considered scalars: * * booleans * * strings * * null * * integers * * floats * * @author Johannes M. Schmitt */ class ScalarNode extends VariableNode { /** * {@inheritDoc} */ protected function validateType($value) { if (!is_scalar($value) && null !== $value) { $ex = new InvalidTypeException(sprintf( 'Invalid type for path "%s". Expected scalar, but got %s.', $this->getPath(), gettype($value) )); $ex->setPath($this->getPath()); throw $ex; } } } PK]m+Config/Definition/FloatNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents a float value in the config tree. * * @author Jeanmonod David */ class FloatNode extends NumericNode { /** * {@inheritDoc} */ protected function validateType($value) { // Integers are also accepted, we just cast them if (is_int($value)) { $value = (float) $value; } if (!is_float($value)) { $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected float, but got %s.', $this->getPath(), gettype($value))); $ex->setPath($this->getPath()); throw $ex; } } } PK]*dd,Config/Definition/ConfigurationInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * Configuration interface * * @author Victor Berchet */ interface ConfigurationInterface { /** * Generates the configuration tree builder. * * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder */ public function getConfigTreeBuilder(); } PK]Un=#'#')Config/Definition/PrototypedArrayNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Exception\DuplicateKeyException; use Symfony\Component\Config\Definition\Exception\UnsetKeyException; use Symfony\Component\Config\Definition\Exception\Exception; /** * Represents a prototyped Array node in the config tree. * * @author Johannes M. Schmitt */ class PrototypedArrayNode extends ArrayNode { protected $prototype; protected $keyAttribute; protected $removeKeyAttribute = false; protected $minNumberOfElements = 0; protected $defaultValue = array(); protected $defaultChildren; /** * Sets the minimum number of elements that a prototype based node must * contain. By default this is zero, meaning no elements. * * @param integer $number */ public function setMinNumberOfElements($number) { $this->minNumberOfElements = $number; } /** * Sets the attribute which value is to be used as key. * * This is useful when you have an indexed array that should be an * associative array. You can select an item from within the array * to be the key of the particular item. For example, if "id" is the * "key", then: * * array( * array('id' => 'my_name', 'foo' => 'bar'), * ); * * becomes * * array( * 'my_name' => array('foo' => 'bar'), * ); * * If you'd like "'id' => 'my_name'" to still be present in the resulting * array, then you can set the second argument of this method to false. * * @param string $attribute The name of the attribute which value is to be used as a key * @param Boolean $remove Whether or not to remove the key */ public function setKeyAttribute($attribute, $remove = true) { $this->keyAttribute = $attribute; $this->removeKeyAttribute = $remove; } /** * Retrieves the name of the attribute which value should be used as key. * * @return string The name of the attribute */ public function getKeyAttribute() { return $this->keyAttribute; } /** * Sets the default value of this node. * * @param string $value * * @throws \InvalidArgumentException if the default value is not an array */ public function setDefaultValue($value) { if (!is_array($value)) { throw new \InvalidArgumentException($this->getPath().': the default value of an array node has to be an array.'); } $this->defaultValue = $value; } /** * Checks if the node has a default value. * * @return Boolean */ public function hasDefaultValue() { return true; } /** * Adds default children when none are set. * * @param integer|string|array|null $children The number of children|The child name|The children names to be added */ public function setAddChildrenIfNoneSet($children = array('defaults')) { if (null === $children) { $this->defaultChildren = array('defaults'); } else { $this->defaultChildren = is_integer($children) && $children > 0 ? range(1, $children) : (array) $children; } } /** * Retrieves the default value. * * The default value could be either explicited or derived from the prototype * default value. * * @return array The default value */ public function getDefaultValue() { if (null !== $this->defaultChildren) { $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : array(); $defaults = array(); foreach (array_values($this->defaultChildren) as $i => $name) { $defaults[null === $this->keyAttribute ? $i : $name] = $default; } return $defaults; } return $this->defaultValue; } /** * Sets the node prototype. * * @param PrototypeNodeInterface $node */ public function setPrototype(PrototypeNodeInterface $node) { $this->prototype = $node; } /** * Retrieves the prototype * * @return PrototypeNodeInterface The prototype */ public function getPrototype() { return $this->prototype; } /** * Disable adding concrete children for prototyped nodes. * * @param NodeInterface $node The child node to add * * @throws Exception */ public function addChild(NodeInterface $node) { throw new Exception('A prototyped array node can not have concrete children.'); } /** * Finalizes the value of this node. * * @param mixed $value * * @return mixed The finalized value * * @throws UnsetKeyException * @throws InvalidConfigurationException if the node doesn't have enough children */ protected function finalizeValue($value) { if (false === $value) { $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value)); throw new UnsetKeyException($msg); } foreach ($value as $k => $v) { $this->prototype->setName($k); try { $value[$k] = $this->prototype->finalize($v); } catch (UnsetKeyException $unset) { unset($value[$k]); } } if (count($value) < $this->minNumberOfElements) { $msg = sprintf('The path "%s" should have at least %d element(s) defined.', $this->getPath(), $this->minNumberOfElements); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } return $value; } /** * Normalizes the value. * * @param mixed $value The value to normalize * * @return mixed The normalized value * * @throws InvalidConfigurationException * @throws DuplicateKeyException */ protected function normalizeValue($value) { if (false === $value) { return $value; } $value = $this->remapXml($value); $isAssoc = array_keys($value) !== range(0, count($value) -1); $normalized = array(); foreach ($value as $k => $v) { if (null !== $this->keyAttribute && is_array($v)) { if (!isset($v[$this->keyAttribute]) && is_int($k) && !$isAssoc) { $msg = sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath()); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } elseif (isset($v[$this->keyAttribute])) { $k = $v[$this->keyAttribute]; // remove the key attribute when required if ($this->removeKeyAttribute) { unset($v[$this->keyAttribute]); } // if only "value" is left if (1 == count($v) && isset($v['value'])) { $v = $v['value']; } } if (array_key_exists($k, $normalized)) { $msg = sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath()); $ex = new DuplicateKeyException($msg); $ex->setPath($this->getPath()); throw $ex; } } $this->prototype->setName($k); if (null !== $this->keyAttribute || $isAssoc) { $normalized[$k] = $this->prototype->normalize($v); } else { $normalized[] = $this->prototype->normalize($v); } } return $normalized; } /** * Merges values together. * * @param mixed $leftSide The left side to merge. * @param mixed $rightSide The right side to merge. * * @return mixed The merged values * * @throws InvalidConfigurationException * @throws \RuntimeException */ protected function mergeValues($leftSide, $rightSide) { if (false === $rightSide) { // if this is still false after the last config has been merged the // finalization pass will take care of removing this key entirely return false; } if (false === $leftSide || !$this->performDeepMerging) { return $rightSide; } foreach ($rightSide as $k => $v) { // prototype, and key is irrelevant, so simply append the element if (null === $this->keyAttribute) { $leftSide[] = $v; continue; } // no conflict if (!array_key_exists($k, $leftSide)) { if (!$this->allowNewKeys) { $ex = new InvalidConfigurationException(sprintf( 'You are not allowed to define new elements for path "%s". ' . 'Please define all elements for this path in one config file.', $this->getPath() )); $ex->setPath($this->getPath()); throw $ex; } $leftSide[$k] = $v; continue; } $this->prototype->setName($k); $leftSide[$k] = $this->prototype->merge($leftSide[$k], $v); } return $leftSide; } } PK]2&&/Config/Definition/Dumper/XmlReferenceDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Dumper; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\NodeInterface; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\EnumNode; use Symfony\Component\Config\Definition\PrototypedArrayNode; /** * Dumps a XML reference configuration for the given configuration/node instance. * * @author Wouter J */ class XmlReferenceDumper { private $reference; public function dump(ConfigurationInterface $configuration, $namespace = null) { return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree(), $namespace); } public function dumpNode(NodeInterface $node, $namespace = null) { $this->reference = ''; $this->writeNode($node, 0, true, $namespace); $ref = $this->reference; $this->reference = null; return $ref; } /** * @param NodeInterface $node * @param integer $depth * @param Boolean $root If the node is the root node * @param string $namespace The namespace of the node */ private function writeNode(NodeInterface $node, $depth = 0, $root = false, $namespace = null) { $rootName = ($root ? 'config' : $node->getName()); $rootNamespace = ($namespace ?: ($root ? 'http://example.org/schema/dic/'.$node->getName() : null)); // xml remapping if ($node->getParent()) { $remapping = array_filter($node->getParent()->getXmlRemappings(), function ($mapping) use ($rootName) { return $rootName === $mapping[1]; }); if (count($remapping)) { list($singular, $plural) = current($remapping); $rootName = $singular; } } $rootName = str_replace('_', '-', $rootName); $rootAttributes = array(); $rootAttributeComments = array(); $rootChildren = array(); $rootComments = array(); if ($node instanceof ArrayNode) { $children = $node->getChildren(); // comments about the root node if ($rootInfo = $node->getInfo()) { $rootComments[] = $rootInfo; } if ($rootNamespace) { $rootComments[] = 'Namespace: '.$rootNamespace; } // render prototyped nodes if ($node instanceof PrototypedArrayNode) { array_unshift($rootComments, 'prototype'); if ($key = $node->getKeyAttribute()) { $rootAttributes[$key] = str_replace('-', ' ', $rootName).' '.$key; } $prototype = $node->getPrototype(); if ($prototype instanceof ArrayNode) { $children = $prototype->getChildren(); } else { if ($prototype->hasDefaultValue()) { $prototypeValue = $prototype->getDefaultValue(); } else { switch (get_class($prototype)) { case 'Symfony\Component\Config\Definition\ScalarNode': $prototypeValue = 'scalar value'; break; case 'Symfony\Component\Config\Definition\FloatNode': case 'Symfony\Component\Config\Definition\IntegerNode': $prototypeValue = 'numeric value'; break; case 'Symfony\Component\Config\Definition\BooleanNode': $prototypeValue = 'true|false'; break; case 'Symfony\Component\Config\Definition\EnumNode': $prototypeValue = implode('|', array_map('json_encode', $prototype->getValues())); break; default: $prototypeValue = 'value'; } } } } // get attributes and elements foreach ($children as $child) { if (!$child instanceof ArrayNode) { // get attributes // metadata $name = str_replace('_', '-', $child->getName()); $value = '%%%%not_defined%%%%'; // use a string which isn't used in the normal world // comments $comments = array(); if ($info = $child->getInfo()) { $comments[] = $info; } if ($example = $child->getExample()) { $comments[] = 'Example: '.$example; } if ($child->isRequired()) { $comments[] = 'Required'; } if ($child instanceof EnumNode) { $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues())); } if (count($comments)) { $rootAttributeComments[$name] = implode(";\n", $comments); } // default values if ($child->hasDefaultValue()) { $value = $child->getDefaultValue(); } // append attribute $rootAttributes[$name] = $value; } else { // get elements $rootChildren[] = $child; } } } // render comments // root node comment if (count($rootComments)) { foreach ($rootComments as $comment) { $this->writeLine('', $depth); } } // attribute comments if (count($rootAttributeComments)) { foreach ($rootAttributeComments as $attrName => $comment) { $commentDepth = $depth + 4 + strlen($attrName) + 2; $commentLines = explode("\n", $comment); $multiline = (count($commentLines) > 1); $comment = implode(PHP_EOL.str_repeat(' ', $commentDepth), $commentLines); if ($multiline) { $this->writeLine('', $depth); } else { $this->writeLine('', $depth); } } } // render start tag + attributes $rootIsVariablePrototype = isset($prototypeValue); $rootIsEmptyTag = (0 === count($rootChildren) && !$rootIsVariablePrototype); $rootOpenTag = '<'.$rootName; if (1 >= ($attributesCount = count($rootAttributes))) { if (1 === $attributesCount) { $rootOpenTag .= sprintf(' %s="%s"', current(array_keys($rootAttributes)), $this->writeValue(current($rootAttributes))); } $rootOpenTag .= $rootIsEmptyTag ? ' />' : '>'; if ($rootIsVariablePrototype) { $rootOpenTag .= $prototypeValue.''; } $this->writeLine($rootOpenTag, $depth); } else { $this->writeLine($rootOpenTag, $depth); $i = 1; foreach ($rootAttributes as $attrName => $attrValue) { $attr = sprintf('%s="%s"', $attrName, $this->writeValue($attrValue)); $this->writeLine($attr, $depth + 4); if ($attributesCount === $i++) { $this->writeLine($rootIsEmptyTag ? '/>' : '>', $depth); if ($rootIsVariablePrototype) { $rootOpenTag .= $prototypeValue.''; } } } } // render children tags foreach ($rootChildren as $child) { $this->writeLine(''); $this->writeNode($child, $depth + 4); } // render end tag if (!$rootIsEmptyTag && !$rootIsVariablePrototype) { $this->writeLine(''); $rootEndTag = ''; $this->writeLine($rootEndTag, $depth); } } /** * Outputs a single config reference line * * @param string $text * @param int $indent */ private function writeLine($text, $indent = 0) { $indent = strlen($text) + $indent; $format = '%'.$indent.'s'; $this->reference .= sprintf($format, $text)."\n"; } /** * Renders the string conversion of the value. * * @param mixed $value * * @return string */ private function writeValue($value) { if ('%%%%not_defined%%%%' === $value) { return ''; } if (is_string($value) || is_numeric($value)) { return $value; } if (false === $value) { return 'false'; } if (true === $value) { return 'true'; } if (null === $value) { return 'null'; } if (empty($value)) { return ''; } if (is_array($value)) { return implode(',', $value); } } } PK]i >>0Config/Definition/Dumper/YamlReferenceDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Dumper; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\NodeInterface; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\ScalarNode; use Symfony\Component\Config\Definition\EnumNode; use Symfony\Component\Config\Definition\PrototypedArrayNode; use Symfony\Component\Yaml\Inline; /** * Dumps a Yaml reference configuration for the given configuration/node instance. * * @author Kevin Bond */ class YamlReferenceDumper { private $reference; public function dump(ConfigurationInterface $configuration) { return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree()); } public function dumpNode(NodeInterface $node) { $this->reference = ''; $this->writeNode($node); $ref = $this->reference; $this->reference = null; return $ref; } /** * @param NodeInterface $node * @param integer $depth */ private function writeNode(NodeInterface $node, $depth = 0) { $comments = array(); $default = ''; $defaultArray = null; $children = null; $example = $node->getExample(); // defaults if ($node instanceof ArrayNode) { $children = $node->getChildren(); if ($node instanceof PrototypedArrayNode) { $prototype = $node->getPrototype(); if ($prototype instanceof ArrayNode) { $children = $prototype->getChildren(); } // check for attribute as key if ($key = $node->getKeyAttribute()) { $keyNodeClass = 'Symfony\Component\Config\Definition\\'.($prototype instanceof ArrayNode ? 'ArrayNode' : 'ScalarNode'); $keyNode = new $keyNodeClass($key, $node); $keyNode->setInfo('Prototype'); // add children foreach ($children as $childNode) { $keyNode->addChild($childNode); } $children = array($key => $keyNode); } } if (!$children) { if ($node->hasDefaultValue() && count($defaultArray = $node->getDefaultValue())) { $default = ''; } elseif (!is_array($example)) { $default = '[]'; } } } elseif ($node instanceof EnumNode) { $comments[] = 'One of '.implode('; ', array_map('json_encode', $node->getValues())); $default = '~'; } else { $default = '~'; if ($node->hasDefaultValue()) { $default = $node->getDefaultValue(); if (is_array($default)) { if (count($defaultArray = $node->getDefaultValue())) { $default = ''; } elseif (!is_array($example)) { $default = '[]'; } } else { $default = Inline::dump($default); } } } // required? if ($node->isRequired()) { $comments[] = 'Required'; } // example if ($example && !is_array($example)) { $comments[] = 'Example: '.$example; } $default = (string) $default != '' ? ' '.$default : ''; $comments = count($comments) ? '# '.implode(', ', $comments) : ''; $text = rtrim(sprintf('%-20s %s %s', $node->getName().':', $default, $comments), ' '); if ($info = $node->getInfo()) { $this->writeLine(''); // indenting multi-line info $info = str_replace("\n", sprintf("\n%".$depth * 4 . "s# ", ' '), $info); $this->writeLine('# '.$info, $depth * 4); } $this->writeLine($text, $depth * 4); // output defaults if ($defaultArray) { $this->writeLine(''); $message = count($defaultArray) > 1 ? 'Defaults' : 'Default'; $this->writeLine('# '.$message.':', $depth * 4 + 4); $this->writeArray($defaultArray, $depth + 1); } if (is_array($example)) { $this->writeLine(''); $message = count($example) > 1 ? 'Examples' : 'Example'; $this->writeLine('# '.$message.':', $depth * 4 + 4); $this->writeArray($example, $depth + 1); } if ($children) { foreach ($children as $childNode) { $this->writeNode($childNode, $depth + 1); } } } /** * Outputs a single config reference line * * @param string $text * @param int $indent */ private function writeLine($text, $indent = 0) { $indent = strlen($text) + $indent; $format = '%'.$indent.'s'; $this->reference .= sprintf($format, $text)."\n"; } private function writeArray(array $array, $depth) { $isIndexed = array_values($array) === $array; foreach ($array as $key => $value) { if (is_array($value)) { $val = ''; } else { $val = $value; } if ($isIndexed) { $this->writeLine('- '.$val, $depth * 4); } else { $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4); } if (is_array($value)) { $this->writeArray($value, $depth + 1); } } } } PK]G4**Config/Definition/ArrayNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; use Symfony\Component\Config\Definition\Exception\UnsetKeyException; /** * Represents an Array node in the config tree. * * @author Johannes M. Schmitt */ class ArrayNode extends BaseNode implements PrototypeNodeInterface { protected $xmlRemappings = array(); protected $children = array(); protected $allowFalse = false; protected $allowNewKeys = true; protected $addIfNotSet = false; protected $performDeepMerging = true; protected $ignoreExtraKeys = false; protected $normalizeKeys = true; public function setNormalizeKeys($normalizeKeys) { $this->normalizeKeys = (Boolean) $normalizeKeys; } /** * Normalizes keys between the different configuration formats. * * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML. * After running this method, all keys are normalized to foo_bar. * * If you have a mixed key like foo-bar_moo, it will not be altered. * The key will also not be altered if the target key already exists. * * @param mixed $value * * @return array The value with normalized keys */ protected function preNormalize($value) { if (!$this->normalizeKeys || !is_array($value)) { return $value; } foreach ($value as $k => $v) { if (false !== strpos($k, '-') && false === strpos($k, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) { $value[$normalizedKey] = $v; unset($value[$k]); } } return $value; } /** * Retrieves the children of this node. * * @return array The children */ public function getChildren() { return $this->children; } /** * Sets the xml remappings that should be performed. * * @param array $remappings an array of the form array(array(string, string)) */ public function setXmlRemappings(array $remappings) { $this->xmlRemappings = $remappings; } /** * Gets the xml remappings that should be performed. * * @return array $remappings an array of the form array(array(string, string)) */ public function getXmlRemappings() { return $this->xmlRemappings; } /** * Sets whether to add default values for this array if it has not been * defined in any of the configuration files. * * @param Boolean $boolean */ public function setAddIfNotSet($boolean) { $this->addIfNotSet = (Boolean) $boolean; } /** * Sets whether false is allowed as value indicating that the array should be unset. * * @param Boolean $allow */ public function setAllowFalse($allow) { $this->allowFalse = (Boolean) $allow; } /** * Sets whether new keys can be defined in subsequent configurations. * * @param Boolean $allow */ public function setAllowNewKeys($allow) { $this->allowNewKeys = (Boolean) $allow; } /** * Sets if deep merging should occur. * * @param Boolean $boolean */ public function setPerformDeepMerging($boolean) { $this->performDeepMerging = (Boolean) $boolean; } /** * Whether extra keys should just be ignore without an exception. * * @param Boolean $boolean To allow extra keys */ public function setIgnoreExtraKeys($boolean) { $this->ignoreExtraKeys = (Boolean) $boolean; } /** * Sets the node Name. * * @param string $name The node's name */ public function setName($name) { $this->name = $name; } /** * Checks if the node has a default value. * * @return Boolean */ public function hasDefaultValue() { return $this->addIfNotSet; } /** * Retrieves the default value. * * @return array The default value * * @throws \RuntimeException if the node has no default value */ public function getDefaultValue() { if (!$this->hasDefaultValue()) { throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath())); } $defaults = array(); foreach ($this->children as $name => $child) { if ($child->hasDefaultValue()) { $defaults[$name] = $child->getDefaultValue(); } } return $defaults; } /** * Adds a child node. * * @param NodeInterface $node The child node to add * * @throws \InvalidArgumentException when the child node has no name * @throws \InvalidArgumentException when the child node's name is not unique */ public function addChild(NodeInterface $node) { $name = $node->getName(); if (!strlen($name)) { throw new \InvalidArgumentException('Child nodes must be named.'); } if (isset($this->children[$name])) { throw new \InvalidArgumentException(sprintf('A child node named "%s" already exists.', $name)); } $this->children[$name] = $node; } /** * Finalizes the value of this node. * * @param mixed $value * * @return mixed The finalised value * * @throws UnsetKeyException * @throws InvalidConfigurationException if the node doesn't have enough children */ protected function finalizeValue($value) { if (false === $value) { $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value)); throw new UnsetKeyException($msg); } foreach ($this->children as $name => $child) { if (!array_key_exists($name, $value)) { if ($child->isRequired()) { $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath()); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } if ($child->hasDefaultValue()) { $value[$name] = $child->getDefaultValue(); } continue; } try { $value[$name] = $child->finalize($value[$name]); } catch (UnsetKeyException $unset) { unset($value[$name]); } } return $value; } /** * Validates the type of the value. * * @param mixed $value * * @throws InvalidTypeException */ protected function validateType($value) { if (!is_array($value) && (!$this->allowFalse || false !== $value)) { $ex = new InvalidTypeException(sprintf( 'Invalid type for path "%s". Expected array, but got %s', $this->getPath(), gettype($value) )); $ex->setPath($this->getPath()); throw $ex; } } /** * Normalizes the value. * * @param mixed $value The value to normalize * * @return mixed The normalized value * * @throws InvalidConfigurationException */ protected function normalizeValue($value) { if (false === $value) { return $value; } $value = $this->remapXml($value); $normalized = array(); foreach ($value as $name => $val) { if (isset($this->children[$name])) { $normalized[$name] = $this->children[$name]->normalize($val); unset($value[$name]); } } // if extra fields are present, throw exception if (count($value) && !$this->ignoreExtraKeys) { $msg = sprintf('Unrecognized options "%s" under "%s"', implode(', ', array_keys($value)), $this->getPath()); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } return $normalized; } /** * Remaps multiple singular values to a single plural value. * * @param array $value The source values * * @return array The remapped values */ protected function remapXml($value) { foreach ($this->xmlRemappings as $transformation) { list($singular, $plural) = $transformation; if (!isset($value[$singular])) { continue; } $value[$plural] = Processor::normalizeConfig($value, $singular, $plural); unset($value[$singular]); } return $value; } /** * Merges values together. * * @param mixed $leftSide The left side to merge. * @param mixed $rightSide The right side to merge. * * @return mixed The merged values * * @throws InvalidConfigurationException * @throws \RuntimeException */ protected function mergeValues($leftSide, $rightSide) { if (false === $rightSide) { // if this is still false after the last config has been merged the // finalization pass will take care of removing this key entirely return false; } if (false === $leftSide || !$this->performDeepMerging) { return $rightSide; } foreach ($rightSide as $k => $v) { // no conflict if (!array_key_exists($k, $leftSide)) { if (!$this->allowNewKeys) { $ex = new InvalidConfigurationException(sprintf( 'You are not allowed to define new elements for path "%s". ' .'Please define all elements for this path in one config file. ' .'If you are trying to overwrite an element, make sure you redefine it ' .'with the same name.', $this->getPath() )); $ex->setPath($this->getPath()); throw $ex; } $leftSide[$k] = $v; continue; } if (!isset($this->children[$k])) { throw new \RuntimeException('merge() expects a normalized config array.'); } $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v); } return $leftSide; } } PK]!Config/Definition/BooleanNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents a Boolean value in the config tree. * * @author Johannes M. Schmitt */ class BooleanNode extends ScalarNode { /** * {@inheritDoc} */ protected function validateType($value) { if (!is_bool($value)) { $ex = new InvalidTypeException(sprintf( 'Invalid type for path "%s". Expected boolean, but got %s.', $this->getPath(), gettype($value) )); $ex->setPath($this->getPath()); throw $ex; } } } PK] })Config/Definition/Builder/NodeBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class provides a fluent interface for building a node. * * @author Johannes M. Schmitt */ class NodeBuilder implements NodeParentInterface { protected $parent; protected $nodeMapping; /** * Constructor * */ public function __construct() { $this->nodeMapping = array( 'variable' => __NAMESPACE__.'\\VariableNodeDefinition', 'scalar' => __NAMESPACE__.'\\ScalarNodeDefinition', 'boolean' => __NAMESPACE__.'\\BooleanNodeDefinition', 'integer' => __NAMESPACE__.'\\IntegerNodeDefinition', 'float' => __NAMESPACE__.'\\FloatNodeDefinition', 'array' => __NAMESPACE__.'\\ArrayNodeDefinition', 'enum' => __NAMESPACE__.'\\EnumNodeDefinition', ); } /** * Set the parent node. * * @param ParentNodeDefinitionInterface $parent The parent node * * @return NodeBuilder This node builder */ public function setParent(ParentNodeDefinitionInterface $parent = null) { $this->parent = $parent; return $this; } /** * Creates a child array node. * * @param string $name The name of the node * * @return ArrayNodeDefinition The child node */ public function arrayNode($name) { return $this->node($name, 'array'); } /** * Creates a child scalar node. * * @param string $name the name of the node * * @return ScalarNodeDefinition The child node */ public function scalarNode($name) { return $this->node($name, 'scalar'); } /** * Creates a child Boolean node. * * @param string $name The name of the node * * @return BooleanNodeDefinition The child node */ public function booleanNode($name) { return $this->node($name, 'boolean'); } /** * Creates a child integer node. * * @param string $name the name of the node * * @return IntegerNodeDefinition The child node */ public function integerNode($name) { return $this->node($name, 'integer'); } /** * Creates a child float node. * * @param string $name the name of the node * * @return FloatNodeDefinition The child node */ public function floatNode($name) { return $this->node($name, 'float'); } /** * Creates a child EnumNode. * * @param string $name * * @return EnumNodeDefinition */ public function enumNode($name) { return $this->node($name, 'enum'); } /** * Creates a child variable node. * * @param string $name The name of the node * * @return VariableNodeDefinition The builder of the child node */ public function variableNode($name) { return $this->node($name, 'variable'); } /** * Returns the parent node. * * @return ParentNodeDefinitionInterface The parent node */ public function end() { return $this->parent; } /** * Creates a child node. * * @param string $name The name of the node * @param string $type The type of the node * * @return NodeDefinition The child node * * @throws \RuntimeException When the node type is not registered * @throws \RuntimeException When the node class is not found */ public function node($name, $type) { $class = $this->getNodeClass($type); $node = new $class($name); $this->append($node); return $node; } /** * Appends a node definition. * * Usage: * * $node = new ArrayNodeDefinition('name') * ->children() * ->scalarNode('foo')->end() * ->scalarNode('baz')->end() * ->append($this->getBarNodeDefinition()) * ->end() * ; * * @param NodeDefinition $node * * @return NodeBuilder This node builder */ public function append(NodeDefinition $node) { if ($node instanceof ParentNodeDefinitionInterface) { $builder = clone $this; $builder->setParent(null); $node->setBuilder($builder); } if (null !== $this->parent) { $this->parent->append($node); // Make this builder the node parent to allow for a fluid interface $node->setParent($this); } return $this; } /** * Adds or overrides a node Type. * * @param string $type The name of the type * @param string $class The fully qualified name the node definition class * * @return NodeBuilder This node builder */ public function setNodeClass($type, $class) { $this->nodeMapping[strtolower($type)] = $class; return $this; } /** * Returns the class name of the node definition. * * @param string $type The node type * * @return string The node definition class name * * @throws \RuntimeException When the node type is not registered * @throws \RuntimeException When the node class is not found */ protected function getNodeClass($type) { $type = strtolower($type); if (!isset($this->nodeMapping[$type])) { throw new \RuntimeException(sprintf('The node type "%s" is not registered.', $type)); } $class = $this->nodeMapping[$type]; if (!class_exists($class)) { throw new \RuntimeException(sprintf('The node class "%s" does not exist.', $class)); } return $class; } } PK]881Config/Definition/Builder/ArrayNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\PrototypedArrayNode; use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; /** * This class provides a fluent interface for defining an array node. * * @author Johannes M. Schmitt */ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface { protected $performDeepMerging = true; protected $ignoreExtraKeys = false; protected $children = array(); protected $prototype; protected $atLeastOne = false; protected $allowNewKeys = true; protected $key; protected $removeKeyItem; protected $addDefaults = false; protected $addDefaultChildren = false; protected $nodeBuilder; protected $normalizeKeys = true; /** * {@inheritDoc} */ public function __construct($name, NodeParentInterface $parent = null) { parent::__construct($name, $parent); $this->nullEquivalent = array(); $this->trueEquivalent = array(); } /** * Sets a custom children builder. * * @param NodeBuilder $builder A custom NodeBuilder */ public function setBuilder(NodeBuilder $builder) { $this->nodeBuilder = $builder; } /** * Returns a builder to add children nodes. * * @return NodeBuilder */ public function children() { return $this->getNodeBuilder(); } /** * Sets a prototype for child nodes. * * @param string $type the type of node * * @return NodeDefinition */ public function prototype($type) { return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this); } /** * Adds the default value if the node is not set in the configuration. * * This method is applicable to concrete nodes only (not to prototype nodes). * If this function has been called and the node is not set during the finalization * phase, it's default value will be derived from its children default values. * * @return ArrayNodeDefinition */ public function addDefaultsIfNotSet() { $this->addDefaults = true; return $this; } /** * Adds children with a default value when none are defined. * * @param integer|string|array|null $children The number of children|The child name|The children names to be added * * This method is applicable to prototype nodes only. * * @return ArrayNodeDefinition */ public function addDefaultChildrenIfNoneSet($children = null) { $this->addDefaultChildren = $children; return $this; } /** * Requires the node to have at least one element. * * This method is applicable to prototype nodes only. * * @return ArrayNodeDefinition */ public function requiresAtLeastOneElement() { $this->atLeastOne = true; return $this; } /** * Disallows adding news keys in a subsequent configuration. * * If used all keys have to be defined in the same configuration file. * * @return ArrayNodeDefinition */ public function disallowNewKeysInSubsequentConfigs() { $this->allowNewKeys = false; return $this; } /** * Sets a normalization rule for XML configurations. * * @param string $singular The key to remap * @param string $plural The plural of the key for irregular plurals * * @return ArrayNodeDefinition */ public function fixXmlConfig($singular, $plural = null) { $this->normalization()->remap($singular, $plural); return $this; } /** * Sets the attribute which value is to be used as key. * * This is useful when you have an indexed array that should be an * associative array. You can select an item from within the array * to be the key of the particular item. For example, if "id" is the * "key", then: * * array( * array('id' => 'my_name', 'foo' => 'bar'), * ); * * becomes * * array( * 'my_name' => array('foo' => 'bar'), * ); * * If you'd like "'id' => 'my_name'" to still be present in the resulting * array, then you can set the second argument of this method to false. * * This method is applicable to prototype nodes only. * * @param string $name The name of the key * @param Boolean $removeKeyItem Whether or not the key item should be removed. * * @return ArrayNodeDefinition */ public function useAttributeAsKey($name, $removeKeyItem = true) { $this->key = $name; $this->removeKeyItem = $removeKeyItem; return $this; } /** * Sets whether the node can be unset. * * @param Boolean $allow * * @return ArrayNodeDefinition */ public function canBeUnset($allow = true) { $this->merge()->allowUnset($allow); return $this; } /** * Adds an "enabled" boolean to enable the current section. * * By default, the section is disabled. If any configuration is specified then * the node will be automatically enabled: * * enableableArrayNode: {enabled: true, ...} # The config is enabled & default values get overridden * enableableArrayNode: ~ # The config is enabled & use the default values * enableableArrayNode: true # The config is enabled & use the default values * enableableArrayNode: {other: value, ...} # The config is enabled & default values get overridden * enableableArrayNode: {enabled: false, ...} # The config is disabled * enableableArrayNode: false # The config is disabled * * @return ArrayNodeDefinition */ public function canBeEnabled() { $this ->addDefaultsIfNotSet() ->treatFalseLike(array('enabled' => false)) ->treatTrueLike(array('enabled' => true)) ->treatNullLike(array('enabled' => true)) ->beforeNormalization() ->ifArray() ->then(function ($v) { $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true; return $v; }) ->end() ->children() ->booleanNode('enabled') ->defaultFalse() ; return $this; } /** * Adds an "enabled" boolean to enable the current section. * * By default, the section is enabled. * * @return ArrayNodeDefinition */ public function canBeDisabled() { $this ->addDefaultsIfNotSet() ->treatFalseLike(array('enabled' => false)) ->treatTrueLike(array('enabled' => true)) ->treatNullLike(array('enabled' => true)) ->children() ->booleanNode('enabled') ->defaultTrue() ; return $this; } /** * Disables the deep merging of the node. * * @return ArrayNodeDefinition */ public function performNoDeepMerging() { $this->performDeepMerging = false; return $this; } /** * Allows extra config keys to be specified under an array without * throwing an exception. * * Those config values are simply ignored. This should be used only * in special cases where you want to send an entire configuration * array through a special tree that processes only part of the array. * * @return ArrayNodeDefinition */ public function ignoreExtraKeys() { $this->ignoreExtraKeys = true; return $this; } /** * Sets key normalization. * * @param Boolean $bool Whether to enable key normalization * * @return ArrayNodeDefinition */ public function normalizeKeys($bool) { $this->normalizeKeys = (Boolean) $bool; return $this; } /** * Appends a node definition. * * $node = new ArrayNodeDefinition() * ->children() * ->scalarNode('foo')->end() * ->scalarNode('baz')->end() * ->end() * ->append($this->getBarNodeDefinition()) * ; * * @param NodeDefinition $node A NodeDefinition instance * * @return ArrayNodeDefinition This node */ public function append(NodeDefinition $node) { $this->children[$node->name] = $node->setParent($this); return $this; } /** * Returns a node builder to be used to add children and prototype * * @return NodeBuilder The node builder */ protected function getNodeBuilder() { if (null === $this->nodeBuilder) { $this->nodeBuilder = new NodeBuilder(); } return $this->nodeBuilder->setParent($this); } /** * {@inheritDoc} */ protected function createNode() { if (null === $this->prototype) { $node = new ArrayNode($this->name, $this->parent); $this->validateConcreteNode($node); $node->setAddIfNotSet($this->addDefaults); foreach ($this->children as $child) { $child->parent = $node; $node->addChild($child->getNode()); } } else { $node = new PrototypedArrayNode($this->name, $this->parent); $this->validatePrototypeNode($node); if (null !== $this->key) { $node->setKeyAttribute($this->key, $this->removeKeyItem); } if (true === $this->atLeastOne) { $node->setMinNumberOfElements(1); } if ($this->default) { $node->setDefaultValue($this->defaultValue); } if (false !== $this->addDefaultChildren) { $node->setAddChildrenIfNoneSet($this->addDefaultChildren); if ($this->prototype instanceof static && null === $this->prototype->prototype) { $this->prototype->addDefaultsIfNotSet(); } } $this->prototype->parent = $node; $node->setPrototype($this->prototype->getNode()); } $node->setAllowNewKeys($this->allowNewKeys); $node->addEquivalentValue(null, $this->nullEquivalent); $node->addEquivalentValue(true, $this->trueEquivalent); $node->addEquivalentValue(false, $this->falseEquivalent); $node->setPerformDeepMerging($this->performDeepMerging); $node->setRequired($this->required); $node->setIgnoreExtraKeys($this->ignoreExtraKeys); $node->setNormalizeKeys($this->normalizeKeys); if (null !== $this->normalization) { $node->setNormalizationClosures($this->normalization->before); $node->setXmlRemappings($this->normalization->remappings); } if (null !== $this->merge) { $node->setAllowOverwrite($this->merge->allowOverwrite); $node->setAllowFalse($this->merge->allowFalse); } if (null !== $this->validation) { $node->setFinalValidationClosures($this->validation->rules); } return $node; } /** * Validate the configuration of a concrete node. * * @param ArrayNode $node The related node * * @throws InvalidDefinitionException */ protected function validateConcreteNode(ArrayNode $node) { $path = $node->getPath(); if (null !== $this->key) { throw new InvalidDefinitionException( sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path) ); } if (true === $this->atLeastOne) { throw new InvalidDefinitionException( sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path) ); } if ($this->default) { throw new InvalidDefinitionException( sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path) ); } if (false !== $this->addDefaultChildren) { throw new InvalidDefinitionException( sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path) ); } } /** * Validate the configuration of a prototype node. * * @param PrototypedArrayNode $node The related node * * @throws InvalidDefinitionException */ protected function validatePrototypeNode(PrototypedArrayNode $node) { $path = $node->getPath(); if ($this->addDefaults) { throw new InvalidDefinitionException( sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path) ); } if (false !== $this->addDefaultChildren) { if ($this->default) { throw new InvalidDefinitionException( sprintf('A default value and default children might not be used together at path "%s"', $path) ); } if (null !== $this->key && (null === $this->addDefaultChildren || is_integer($this->addDefaultChildren) && $this->addDefaultChildren > 0)) { throw new InvalidDefinitionException( sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path) ); } if (null === $this->key && (is_string($this->addDefaultChildren) || is_array($this->addDefaultChildren))) { throw new InvalidDefinitionException( sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path) ); } } } } PK]{{*Config/Definition/Builder/MergeBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class builds merge conditions. * * @author Johannes M. Schmitt */ class MergeBuilder { protected $node; public $allowFalse = false; public $allowOverwrite = true; /** * Constructor * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Sets whether the node can be unset. * * @param Boolean $allow * * @return MergeBuilder */ public function allowUnset($allow = true) { $this->allowFalse = $allow; return $this; } /** * Sets whether the node can be overwritten. * * @param Boolean $deny Whether the overwriting is forbidden or not * * @return MergeBuilder */ public function denyOverwrite($deny = true) { $this->allowOverwrite = !$deny; return $this; } /** * Returns the related node. * * @return NodeDefinition */ public function end() { return $this->node; } } PK]# ֕442Config/Definition/Builder/NormalizationBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class builds normalization conditions. * * @author Johannes M. Schmitt */ class NormalizationBuilder { protected $node; public $before = array(); public $remappings = array(); /** * Constructor * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Registers a key to remap to its plural form. * * @param string $key The key to remap * @param string $plural The plural of the key in case of irregular plural * * @return NormalizationBuilder */ public function remap($key, $plural = null) { $this->remappings[] = array($key, null === $plural ? $key.'s' : $plural); return $this; } /** * Registers a closure to run before the normalization or an expression builder to build it if null is provided. * * @param \Closure $closure * * @return ExprBuilder|NormalizationBuilder */ public function before(\Closure $closure = null) { if (null !== $closure) { $this->before[] = $closure; return $this; } return $this->before[] = new ExprBuilder($this->node); } } PK]'nڭ3Config/Definition/Builder/IntegerNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\IntegerNode; /** * This class provides a fluent interface for defining an integer node. * * @author Jeanmonod David */ class IntegerNodeDefinition extends NumericNodeDefinition { /** * Instantiates a Node. * * @return IntegerNode The node */ protected function instantiateNode() { return new IntegerNode($this->name, $this->parent, $this->min, $this->max); } } PK]mc2Config/Definition/Builder/ScalarNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\ScalarNode; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ class ScalarNodeDefinition extends VariableNodeDefinition { /** * Instantiate a Node * * @return ScalarNode The node */ protected function instantiateNode() { return new ScalarNode($this->name, $this->parent); } } PK]~GXX3Config/Definition/Builder/NumericNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * Abstract class that contain common code of integer and float node definition. * * @author David Jeanmonod */ abstract class NumericNodeDefinition extends ScalarNodeDefinition { protected $min; protected $max; /** * Ensures that the value is smaller than the given reference. * * @param mixed $max * * @return NumericNodeDefinition * * @throws \InvalidArgumentException when the constraint is inconsistent */ public function max($max) { if (isset($this->min) && $this->min > $max) { throw new \InvalidArgumentException(sprintf('You cannot define a max(%s) as you already have a min(%s)', $max, $this->min)); } $this->max = $max; return $this; } /** * Ensures that the value is bigger than the given reference. * * @param mixed $min * * @return NumericNodeDefinition * * @throws \InvalidArgumentException when the constraint is inconsistent */ public function min($min) { if (isset($this->max) && $this->max < $min) { throw new \InvalidArgumentException(sprintf('You cannot define a min(%s) as you already have a max(%s)', $min, $this->max)); } $this->min = $min; return $this; } } PK]U=1Config/Definition/Builder/NodeParentInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * An interface that must be implemented by all node parents * * @author Victor Berchet */ interface NodeParentInterface { } PK]e@4Config/Definition/Builder/VariableNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\VariableNode; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ class VariableNodeDefinition extends NodeDefinition { /** * Instantiate a Node * * @return VariableNode The node */ protected function instantiateNode() { return new VariableNode($this->name, $this->parent); } /** * {@inheritDoc} */ protected function createNode() { $node = $this->instantiateNode(); if (null !== $this->normalization) { $node->setNormalizationClosures($this->normalization->before); } if (null !== $this->merge) { $node->setAllowOverwrite($this->merge->allowOverwrite); } if (true === $this->default) { $node->setDefaultValue($this->defaultValue); } $node->setAllowEmptyValue($this->allowEmptyValue); $node->addEquivalentValue(null, $this->nullEquivalent); $node->addEquivalentValue(true, $this->trueEquivalent); $node->addEquivalentValue(false, $this->falseEquivalent); $node->setRequired($this->required); if (null !== $this->validation) { $node->setFinalValidationClosures($this->validation->rules); } return $node; } } PK]VhU)Config/Definition/Builder/TreeBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\NodeInterface; /** * This is the entry class for building a config tree. * * @author Johannes M. Schmitt */ class TreeBuilder implements NodeParentInterface { protected $tree; protected $root; protected $builder; /** * Creates the root node. * * @param string $name The name of the root node * @param string $type The type of the root node * @param NodeBuilder $builder A custom node builder instance * * @return ArrayNodeDefinition|NodeDefinition The root node (as an ArrayNodeDefinition when the type is 'array') * * @throws \RuntimeException When the node type is not supported */ public function root($name, $type = 'array', NodeBuilder $builder = null) { $builder = $builder ?: new NodeBuilder(); return $this->root = $builder->node($name, $type)->setParent($this); } /** * Builds the tree. * * @return NodeInterface * * @throws \RuntimeException */ public function buildTree() { if (null === $this->root) { throw new \RuntimeException('The configuration tree has no root node.'); } if (null !== $this->tree) { return $this->tree; } return $this->tree = $this->root->getNode(true); } } PK]tp1Config/Definition/Builder/FloatNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\FloatNode; /** * This class provides a fluent interface for defining a float node. * * @author Jeanmonod David */ class FloatNodeDefinition extends NumericNodeDefinition { /** * Instantiates a Node. * * @return FloatNode The node */ protected function instantiateNode() { return new FloatNode($this->name, $this->parent, $this->min, $this->max); } } PK] "$$)Config/Definition/Builder/ExprBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\Exception\UnsetKeyException; /** * This class builds an if expression. * * @author Johannes M. Schmitt * @author Christophe Coevoet */ class ExprBuilder { protected $node; public $ifPart; public $thenPart; /** * Constructor * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Marks the expression as being always used. * * @param \Closure $then * * @return ExprBuilder */ public function always(\Closure $then = null) { $this->ifPart = function ($v) { return true; }; if (null !== $then) { $this->thenPart = $then; } return $this; } /** * Sets a closure to use as tests. * * The default one tests if the value is true. * * @param \Closure $closure * * @return ExprBuilder */ public function ifTrue(\Closure $closure = null) { if (null === $closure) { $closure = function ($v) { return true === $v; }; } $this->ifPart = $closure; return $this; } /** * Tests if the value is a string. * * @return ExprBuilder */ public function ifString() { $this->ifPart = function ($v) { return is_string($v); }; return $this; } /** * Tests if the value is null. * * @return ExprBuilder */ public function ifNull() { $this->ifPart = function ($v) { return null === $v; }; return $this; } /** * Tests if the value is an array. * * @return ExprBuilder */ public function ifArray() { $this->ifPart = function ($v) { return is_array($v); }; return $this; } /** * Tests if the value is in an array. * * @param array $array * * @return ExprBuilder */ public function ifInArray(array $array) { $this->ifPart = function ($v) use ($array) { return in_array($v, $array, true); }; return $this; } /** * Tests if the value is not in an array. * * @param array $array * * @return ExprBuilder */ public function ifNotInArray(array $array) { $this->ifPart = function ($v) use ($array) { return !in_array($v, $array, true); }; return $this; } /** * Sets the closure to run if the test pass. * * @param \Closure $closure * * @return ExprBuilder */ public function then(\Closure $closure) { $this->thenPart = $closure; return $this; } /** * Sets a closure returning an empty array. * * @return ExprBuilder */ public function thenEmptyArray() { $this->thenPart = function ($v) { return array(); }; return $this; } /** * Sets a closure marking the value as invalid at validation time. * * if you want to add the value of the node in your message just use a %s placeholder. * * @param string $message * * @return ExprBuilder * * @throws \InvalidArgumentException */ public function thenInvalid($message) { $this->thenPart = function ($v) use ($message) {throw new \InvalidArgumentException(sprintf($message, json_encode($v))); }; return $this; } /** * Sets a closure unsetting this key of the array at validation time. * * @return ExprBuilder * * @throws UnsetKeyException */ public function thenUnset() { $this->thenPart = function ($v) { throw new UnsetKeyException('Unsetting key'); }; return $this; } /** * Returns the related node * * @return NodeDefinition * * @throws \RuntimeException */ public function end() { if (null === $this->ifPart) { throw new \RuntimeException('You must specify an if part.'); } if (null === $this->thenPart) { throw new \RuntimeException('You must specify a then part.'); } return $this->node; } /** * Builds the expressions. * * @param ExprBuilder[] $expressions An array of ExprBuilder instances to build * * @return array */ public static function buildExpressions(array $expressions) { foreach ($expressions as $k => $expr) { if ($expr instanceof ExprBuilder) { $expressions[$k] = function ($v) use ($expr) { return call_user_func($expr->ifPart, $v) ? call_user_func($expr->thenPart, $v) : $v; }; } } return $expressions; } } PK]ʍ0Config/Definition/Builder/EnumNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\EnumNode; /** * Enum Node Definition. * * @author Johannes M. Schmitt */ class EnumNodeDefinition extends ScalarNodeDefinition { private $values; public function values(array $values) { $values = array_unique($values); if (count($values) <= 1) { throw new \InvalidArgumentException('->values() must be called with at least two distinct values.'); } $this->values = $values; return $this; } /** * Instantiate a Node * * @return EnumNode The node * * @throws \RuntimeException */ protected function instantiateNode() { if (null === $this->values) { throw new \RuntimeException('You must call ->values() on enum nodes.'); } return new EnumNode($this->name, $this->parent, $this->values); } } PK],l[[/Config/Definition/Builder/ValidationBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class builds validation conditions. * * @author Christophe Coevoet */ class ValidationBuilder { protected $node; public $rules = array(); /** * Constructor * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Registers a closure to run as normalization or an expression builder to build it if null is provided. * * @param \Closure $closure * * @return ExprBuilder|ValidationBuilder */ public function rule(\Closure $closure = null) { if (null !== $closure) { $this->rules[] = $closure; return $this; } return $this->rules[] = new ExprBuilder($this->node); } } PK]K,Config/Definition/Builder/NodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\NodeInterface; use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ abstract class NodeDefinition implements NodeParentInterface { protected $name; protected $normalization; protected $validation; protected $defaultValue; protected $default = false; protected $required = false; protected $merge; protected $allowEmptyValue = true; protected $nullEquivalent; protected $trueEquivalent = true; protected $falseEquivalent = false; /** * @var NodeParentInterface|null */ protected $parent; protected $attributes = array(); /** * Constructor * * @param string $name The name of the node * @param NodeParentInterface|null $parent The parent */ public function __construct($name, NodeParentInterface $parent = null) { $this->parent = $parent; $this->name = $name; } /** * Sets the parent node. * * @param NodeParentInterface $parent The parent * * @return NodeDefinition */ public function setParent(NodeParentInterface $parent) { $this->parent = $parent; return $this; } /** * Sets info message. * * @param string $info The info text * * @return NodeDefinition */ public function info($info) { return $this->attribute('info', $info); } /** * Sets example configuration. * * @param string|array $example * * @return NodeDefinition */ public function example($example) { return $this->attribute('example', $example); } /** * Sets an attribute on the node. * * @param string $key * @param mixed $value * * @return NodeDefinition */ public function attribute($key, $value) { $this->attributes[$key] = $value; return $this; } /** * Returns the parent node. * * @return NodeParentInterface|null The builder of the parent node */ public function end() { return $this->parent; } /** * Creates the node. * * @param Boolean $forceRootNode Whether to force this node as the root node * * @return NodeInterface */ public function getNode($forceRootNode = false) { if ($forceRootNode) { $this->parent = null; } if (null !== $this->normalization) { $this->normalization->before = ExprBuilder::buildExpressions($this->normalization->before); } if (null !== $this->validation) { $this->validation->rules = ExprBuilder::buildExpressions($this->validation->rules); } $node = $this->createNode(); $node->setAttributes($this->attributes); return $node; } /** * Sets the default value. * * @param mixed $value The default value * * @return NodeDefinition */ public function defaultValue($value) { $this->default = true; $this->defaultValue = $value; return $this; } /** * Sets the node as required. * * @return NodeDefinition */ public function isRequired() { $this->required = true; return $this; } /** * Sets the equivalent value used when the node contains null. * * @param mixed $value * * @return NodeDefinition */ public function treatNullLike($value) { $this->nullEquivalent = $value; return $this; } /** * Sets the equivalent value used when the node contains true. * * @param mixed $value * * @return NodeDefinition */ public function treatTrueLike($value) { $this->trueEquivalent = $value; return $this; } /** * Sets the equivalent value used when the node contains false. * * @param mixed $value * * @return NodeDefinition */ public function treatFalseLike($value) { $this->falseEquivalent = $value; return $this; } /** * Sets null as the default value. * * @return NodeDefinition */ public function defaultNull() { return $this->defaultValue(null); } /** * Sets true as the default value. * * @return NodeDefinition */ public function defaultTrue() { return $this->defaultValue(true); } /** * Sets false as the default value. * * @return NodeDefinition */ public function defaultFalse() { return $this->defaultValue(false); } /** * Sets an expression to run before the normalization. * * @return ExprBuilder */ public function beforeNormalization() { return $this->normalization()->before(); } /** * Denies the node value being empty. * * @return NodeDefinition */ public function cannotBeEmpty() { $this->allowEmptyValue = false; return $this; } /** * Sets an expression to run for the validation. * * The expression receives the value of the node and must return it. It can * modify it. * An exception should be thrown when the node is not valid. * * @return ExprBuilder */ public function validate() { return $this->validation()->rule(); } /** * Sets whether the node can be overwritten. * * @param Boolean $deny Whether the overwriting is forbidden or not * * @return NodeDefinition */ public function cannotBeOverwritten($deny = true) { $this->merge()->denyOverwrite($deny); return $this; } /** * Gets the builder for validation rules. * * @return ValidationBuilder */ protected function validation() { if (null === $this->validation) { $this->validation = new ValidationBuilder($this); } return $this->validation; } /** * Gets the builder for merging rules. * * @return MergeBuilder */ protected function merge() { if (null === $this->merge) { $this->merge = new MergeBuilder($this); } return $this->merge; } /** * Gets the builder for normalization rules. * * @return NormalizationBuilder */ protected function normalization() { if (null === $this->normalization) { $this->normalization = new NormalizationBuilder($this); } return $this->normalization; } /** * Instantiate and configure the node according to this definition * * @return NodeInterface $node The node instance * * @throws InvalidDefinitionException When the definition is invalid */ abstract protected function createNode(); } PK]P3Config/Definition/Builder/BooleanNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\BooleanNode; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ class BooleanNodeDefinition extends ScalarNodeDefinition { /** * {@inheritDoc} */ public function __construct($name, NodeParentInterface $parent = null) { parent::__construct($name, $parent); $this->nullEquivalent = true; } /** * Instantiate a Node * * @return BooleanNode The node */ protected function instantiateNode() { return new BooleanNode($this->name, $this->parent); } } PK]3d__;Config/Definition/Builder/ParentNodeDefinitionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * An interface that must be implemented by nodes which can have children * * @author Victor Berchet */ interface ParentNodeDefinitionInterface { public function children(); public function append(NodeDefinition $node); public function setBuilder(NodeBuilder $builder); } PK]]F4:Config/Definition/Exception/InvalidDefinitionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * Thrown when an error is detected in a node Definition. * * @author Victor Berchet */ class InvalidDefinitionException extends Exception { } PK]|EE5Config/Definition/Exception/DuplicateKeyException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is thrown whenever the key of an array is not unique. This can * only be the case if the configuration is coming from an XML file. * * @author Johannes M. Schmitt */ class DuplicateKeyException extends InvalidConfigurationException { } PK]@4Config/Definition/Exception/InvalidTypeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is thrown if an invalid type is encountered. * * @author Johannes M. Schmitt */ class InvalidTypeException extends InvalidConfigurationException { } PK]1Config/Definition/Exception/UnsetKeyException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is usually not encountered by the end-user, but only used * internally to signal the parent scope to unset a key. * * @author Johannes M. Schmitt */ class UnsetKeyException extends Exception { } PK]5-=Config/Definition/Exception/InvalidConfigurationException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * A very general exception which can be thrown whenever non of the more specific * exceptions is suitable. * * @author Johannes M. Schmitt */ class InvalidConfigurationException extends Exception { private $path; public function setPath($path) { $this->path = $path; } public function getPath() { return $this->path; } } PK]C)Config/Definition/Exception/Exception.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * Base exception for all configuration exceptions * * @author Johannes M. Schmitt */ class Exception extends \RuntimeException { } PK]:2&QQ;Config/Definition/Exception/ForbiddenOverwriteException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is thrown when a configuration path is overwritten from a * subsequent configuration file, but the entry node specifically forbids this. * * @author Johannes M. Schmitt */ class ForbiddenOverwriteException extends InvalidConfigurationException { } PK]-*ҹ--!Config/Definition/NumericNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; /** * This node represents a numeric value in the config tree * * @author David Jeanmonod */ class NumericNode extends ScalarNode { protected $min; protected $max; public function __construct($name, NodeInterface $parent = null, $min = null, $max = null) { parent::__construct($name, $parent); $this->min = $min; $this->max = $max; } /** * {@inheritDoc} */ protected function finalizeValue($value) { $value = parent::finalizeValue($value); $errorMsg = null; if (isset($this->min) && $value < $this->min) { $errorMsg = sprintf('The value %s is too small for path "%s". Should be greater than or equal to %s', $value, $this->getPath(), $this->min); } if (isset($this->max) && $value > $this->max) { $errorMsg = sprintf('The value %s is too big for path "%s". Should be less than or equal to %s', $value, $this->getPath(), $this->max); } if (isset($errorMsg)) { $ex = new InvalidConfigurationException($errorMsg); $ex->setPath($this->getPath()); throw $ex; } return $value; } } PK]$¸ "Config/Definition/VariableNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; /** * This node represents a value of variable type in the config tree. * * This node is intended for values of arbitrary type. * Any PHP type is accepted as a value. * * @author Jeremy Mikola */ class VariableNode extends BaseNode implements PrototypeNodeInterface { protected $defaultValueSet = false; protected $defaultValue; protected $allowEmptyValue = true; /** * {@inheritDoc} */ public function setDefaultValue($value) { $this->defaultValueSet = true; $this->defaultValue = $value; } /** * {@inheritDoc} */ public function hasDefaultValue() { return $this->defaultValueSet; } /** * {@inheritDoc} */ public function getDefaultValue() { return $this->defaultValue instanceof \Closure ? call_user_func($this->defaultValue) : $this->defaultValue; } /** * Sets if this node is allowed to have an empty value. * * @param Boolean $boolean True if this entity will accept empty values. */ public function setAllowEmptyValue($boolean) { $this->allowEmptyValue = (Boolean) $boolean; } /** * {@inheritDoc} */ public function setName($name) { $this->name = $name; } /** * {@inheritDoc} */ protected function validateType($value) { } /** * {@inheritDoc} */ protected function finalizeValue($value) { if (!$this->allowEmptyValue && empty($value)) { $ex = new InvalidConfigurationException(sprintf( 'The path "%s" cannot contain an empty value, but got %s.', $this->getPath(), json_encode($value) )); $ex->setPath($this->getPath()); throw $ex; } return $value; } /** * {@inheritDoc} */ protected function normalizeValue($value) { return $value; } /** * {@inheritDoc} */ protected function mergeValues($leftSide, $rightSide) { return $rightSide; } } PK]aVp  Config/Definition/EnumNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; /** * Node which only allows a finite set of values. * * @author Johannes M. Schmitt */ class EnumNode extends ScalarNode { private $values; public function __construct($name, NodeInterface $parent = null, array $values = array()) { $values = array_unique($values); if (count($values) <= 1) { throw new \InvalidArgumentException('$values must contain at least two distinct elements.'); } parent::__construct($name, $parent); $this->values = $values; } public function getValues() { return $this->values; } protected function finalizeValue($value) { $value = parent::finalizeValue($value); if (!in_array($value, $this->values, true)) { $ex = new InvalidConfigurationException(sprintf( 'The value %s is not allowed for path "%s". Permissible values: %s', json_encode($value), $this->getPath(), implode(', ', array_map('json_encode', $this->values)))); $ex->setPath($this->getPath()); throw $ex; } return $value; } } PK]U' ' Config/Definition/Processor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * This class is the entry point for config normalization/merging/finalization. * * @author Johannes M. Schmitt */ class Processor { /** * Processes an array of configurations. * * @param NodeInterface $configTree The node tree describing the configuration * @param array $configs An array of configuration items to process * * @return array The processed configuration */ public function process(NodeInterface $configTree, array $configs) { $currentConfig = array(); foreach ($configs as $config) { $config = $configTree->normalize($config); $currentConfig = $configTree->merge($currentConfig, $config); } return $configTree->finalize($currentConfig); } /** * Processes an array of configurations. * * @param ConfigurationInterface $configuration The configuration class * @param array $configs An array of configuration items to process * * @return array The processed configuration */ public function processConfiguration(ConfigurationInterface $configuration, array $configs) { return $this->process($configuration->getConfigTreeBuilder()->buildTree(), $configs); } /** * Normalizes a configuration entry. * * This method returns a normalize configuration array for a given key * to remove the differences due to the original format (YAML and XML mainly). * * Here is an example. * * The configuration in XML: * * twig.extension.foo * twig.extension.bar * * And the same configuration in YAML: * * extensions: ['twig.extension.foo', 'twig.extension.bar'] * * @param array $config A config array * @param string $key The key to normalize * @param string $plural The plural form of the key if it is irregular * * @return array */ public static function normalizeConfig($config, $key, $plural = null) { if (null === $plural) { $plural = $key.'s'; } if (isset($config[$plural])) { return $config[$plural]; } if (isset($config[$key])) { if (is_string($config[$key]) || !is_int(key($config[$key]))) { // only one return array($config[$key]); } return $config[$key]; } return array(); } } PK]fJ#Config/Definition/NodeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * Common Interface among all nodes. * * In most cases, it is better to inherit from BaseNode instead of implementing * this interface yourself. * * @author Johannes M. Schmitt */ interface NodeInterface { /** * Returns the name of the node. * * @return string The name of the node */ public function getName(); /** * Returns the path of the node. * * @return string The node path */ public function getPath(); /** * Returns true when the node is required. * * @return Boolean If the node is required */ public function isRequired(); /** * Returns true when the node has a default value. * * @return Boolean If the node has a default value */ public function hasDefaultValue(); /** * Returns the default value of the node. * * @return mixed The default value * @throws \RuntimeException if the node has no default value */ public function getDefaultValue(); /** * Normalizes the supplied value. * * @param mixed $value The value to normalize * * @return mixed The normalized value */ public function normalize($value); /** * Merges two values together. * * @param mixed $leftSide * @param mixed $rightSide * * @return mixed The merged values */ public function merge($leftSide, $rightSide); /** * Finalizes a value. * * @param mixed $value The value to finalize * * @return mixed The finalized value */ public function finalize($value); } PK]000%Config/Definition/ReferenceDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper; /** * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper instead. */ class ReferenceDumper extends YamlReferenceDumper { } PK]=Config/Loader/Loader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; use Symfony\Component\Config\Exception\FileLoaderLoadException; /** * Loader is the abstract class used by all built-in loaders. * * @author Fabien Potencier */ abstract class Loader implements LoaderInterface { protected $resolver; /** * Gets the loader resolver. * * @return LoaderResolverInterface A LoaderResolverInterface instance */ public function getResolver() { return $this->resolver; } /** * Sets the loader resolver. * * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance */ public function setResolver(LoaderResolverInterface $resolver) { $this->resolver = $resolver; } /** * Imports a resource. * * @param mixed $resource A Resource * @param string $type The resource type * * @return mixed */ public function import($resource, $type = null) { return $this->resolve($resource, $type)->load($resource, $type); } /** * Finds a loader able to load an imported resource. * * @param mixed $resource A Resource * @param string $type The resource type * * @return LoaderInterface A LoaderInterface instance * * @throws FileLoaderLoadException if no loader is found */ public function resolve($resource, $type = null) { if ($this->supports($resource, $type)) { return $this; } $loader = null === $this->resolver ? false : $this->resolver->resolve($resource, $type); if (false === $loader) { throw new FileLoaderLoadException($resource); } return $loader; } } PK])Config/Loader/LoaderResolverInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; /** * LoaderResolverInterface selects a loader for a given resource. * * @author Fabien Potencier */ interface LoaderResolverInterface { /** * Returns a loader able to load the resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return LoaderInterface A LoaderInterface instance */ public function resolve($resource, $type = null); } PK]__wP< < Config/Loader/FileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; use Symfony\Component\Config\FileLocatorInterface; use Symfony\Component\Config\Exception\FileLoaderLoadException; use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException; /** * FileLoader is the abstract class used by all built-in loaders that are file based. * * @author Fabien Potencier */ abstract class FileLoader extends Loader { protected static $loading = array(); protected $locator; private $currentDir; /** * Constructor. * * @param FileLocatorInterface $locator A FileLocatorInterface instance */ public function __construct(FileLocatorInterface $locator) { $this->locator = $locator; } public function setCurrentDir($dir) { $this->currentDir = $dir; } public function getLocator() { return $this->locator; } /** * Imports a resource. * * @param mixed $resource A Resource * @param string $type The resource type * @param Boolean $ignoreErrors Whether to ignore import errors or not * @param string $sourceResource The original resource importing the new resource * * @return mixed * * @throws FileLoaderLoadException * @throws FileLoaderImportCircularReferenceException */ public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null) { try { $loader = $this->resolve($resource, $type); if ($loader instanceof FileLoader && null !== $this->currentDir) { // we fallback to the current locator to keep BC // as some some loaders do not call the parent __construct() // @deprecated should be removed in 3.0 $locator = $loader->getLocator() ?: $this->locator; $resource = $locator->locate($resource, $this->currentDir, false); } $resources = is_array($resource) ? $resource : array($resource); for ($i = 0; $i < $resourcesCount = count($resources); $i++ ) { if (isset(self::$loading[$resources[$i]])) { if ($i == $resourcesCount-1) { throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading)); } } else { $resource = $resources[$i]; break; } } self::$loading[$resource] = true; $ret = $loader->load($resource, $type); unset(self::$loading[$resource]); return $ret; } catch (FileLoaderImportCircularReferenceException $e) { throw $e; } catch (\Exception $e) { if (!$ignoreErrors) { // prevent embedded imports from nesting multiple exceptions if ($e instanceof FileLoaderLoadException) { throw $e; } throw new FileLoaderLoadException($resource, $sourceResource, null, $e); } } } } PK]499!Config/Loader/LoaderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; /** * LoaderInterface is the interface implemented by all loader classes. * * @author Fabien Potencier */ interface LoaderInterface { /** * Loads a resource. * * @param mixed $resource The resource * @param string $type The resource type */ public function load($resource, $type = null); /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null); /** * Gets the loader resolver. * * @return LoaderResolverInterface A LoaderResolverInterface instance */ public function getResolver(); /** * Sets the loader resolver. * * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance */ public function setResolver(LoaderResolverInterface $resolver); } PK]HPʉ Config/Loader/LoaderResolver.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; /** * LoaderResolver selects a loader for a given resource. * * A resource can be anything (e.g. a full path to a config file or a Closure). * Each loader determines whether it can load a resource and how. * * @author Fabien Potencier */ class LoaderResolver implements LoaderResolverInterface { /** * @var LoaderInterface[] An array of LoaderInterface objects */ private $loaders = array(); /** * Constructor. * * @param LoaderInterface[] $loaders An array of loaders */ public function __construct(array $loaders = array()) { foreach ($loaders as $loader) { $this->addLoader($loader); } } /** * Returns a loader able to load the resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return LoaderInterface|false A LoaderInterface instance */ public function resolve($resource, $type = null) { foreach ($this->loaders as $loader) { if ($loader->supports($resource, $type)) { return $loader; } } return false; } /** * Adds a loader. * * @param LoaderInterface $loader A LoaderInterface instance */ public function addLoader(LoaderInterface $loader) { $this->loaders[] = $loader; $loader->setResolver($this); } /** * Returns the registered loaders. * * @return LoaderInterface[] An array of LoaderInterface instances */ public function getLoaders() { return $this->loaders; } } PK]))"Config/Loader/DelegatingLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; use Symfony\Component\Config\Exception\FileLoaderLoadException; /** * DelegatingLoader delegates loading to other loaders using a loader resolver. * * This loader acts as an array of LoaderInterface objects - each having * a chance to load a given resource (handled by the resolver) * * @author Fabien Potencier */ class DelegatingLoader extends Loader { /** * Constructor. * * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance */ public function __construct(LoaderResolverInterface $resolver) { $this->resolver = $resolver; } /** * Loads a resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return mixed * * @throws FileLoaderLoadException if no loader is found. */ public function load($resource, $type = null) { if (false === $loader = $this->resolver->resolve($resource, $type)) { throw new FileLoaderLoadException($resource); } return $loader->load($resource, $type); } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return false !== $this->resolver->resolve($resource, $type); } } PK]W ,Config/Exception/FileLoaderLoadException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Exception; /** * Exception class for when a resource cannot be loaded or imported. * * @author Ryan Weaver */ class FileLoaderLoadException extends \Exception { /** * @param string $resource The resource that could not be imported * @param string $sourceResource The original resource importing the new resource * @param integer $code The error code * @param \Exception $previous A previous exception */ public function __construct($resource, $sourceResource = null, $code = null, $previous = null) { if (null === $sourceResource) { $message = sprintf('Cannot load resource "%s".', $this->varToString($resource)); } else { $message = sprintf('Cannot import resource "%s" from "%s".', $this->varToString($resource), $this->varToString($sourceResource)); } // Is the resource located inside a bundle? if ('@' === $resource[0]) { $parts = explode(DIRECTORY_SEPARATOR, $resource); $bundle = substr($parts[0], 1); $message .= ' '.sprintf('Make sure the "%s" bundle is correctly registered and loaded in the application kernel class.', $bundle); } elseif ($previous) { // include the previous exception, to help the user see what might be the underlying cause $message .= ' '.sprintf('(%s)', $previous->getMessage()); } parent::__construct($message, $code, $previous); } protected function varToString($var) { if (is_object($var)) { return sprintf('Object(%s)', get_class($var)); } if (is_array($var)) { $a = array(); foreach ($var as $k => $v) { $a[] = sprintf('%s => %s', $k, $this->varToString($v)); } return sprintf("Array(%s)", implode(', ', $a)); } if (is_resource($var)) { return sprintf('Resource(%s)', get_resource_type($var)); } if (null === $var) { return 'null'; } if (false === $var) { return 'false'; } if (true === $var) { return 'true'; } return (string) $var; } } PK]7 TT?Config/Exception/FileLoaderImportCircularReferenceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Exception; /** * Exception class for when a circular reference is detected when importing resources. * * @author Fabien Potencier */ class FileLoaderImportCircularReferenceException extends FileLoaderLoadException { public function __construct(array $resources, $code = null, $previous = null) { $message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]); call_user_func('Exception::__construct', $message, $code, $previous); } } PK]fKEDD%Config/Resource/ResourceInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Resource; /** * ResourceInterface is the interface that must be implemented by all Resource classes. * * @author Fabien Potencier */ interface ResourceInterface { /** * Returns a string representation of the Resource. * * @return string A string representation of the Resource */ public function __toString(); /** * Returns true if the resource has not been updated since the given timestamp. * * @param integer $timestamp The last time the resource was loaded * * @return Boolean true if the resource has not been updated, false otherwise */ public function isFresh($timestamp); /** * Returns the resource tied to this Resource. * * @return mixed The resource */ public function getResource(); } PK] # %Config/Resource/DirectoryResource.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Resource; /** * DirectoryResource represents a resources stored in a subdirectory tree. * * @author Fabien Potencier */ class DirectoryResource implements ResourceInterface, \Serializable { private $resource; private $pattern; /** * Constructor. * * @param string $resource The file path to the resource * @param string $pattern A pattern to restrict monitored files */ public function __construct($resource, $pattern = null) { $this->resource = $resource; $this->pattern = $pattern; } /** * Returns a string representation of the Resource. * * @return string A string representation of the Resource */ public function __toString() { return (string) $this->resource; } /** * Returns the resource tied to this Resource. * * @return mixed The resource */ public function getResource() { return $this->resource; } public function getPattern() { return $this->pattern; } /** * Returns true if the resource has not been updated since the given timestamp. * * @param integer $timestamp The last time the resource was loaded * * @return Boolean true if the resource has not been updated, false otherwise */ public function isFresh($timestamp) { if (!is_dir($this->resource)) { return false; } $newestMTime = filemtime($this->resource); foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->resource), \RecursiveIteratorIterator::SELF_FIRST) as $file) { // if regex filtering is enabled only check matching files if ($this->pattern && $file->isFile() && !preg_match($this->pattern, $file->getBasename())) { continue; } // always monitor directories for changes, except the .. entries // (otherwise deleted files wouldn't get detected) if ($file->isDir() && '/..' === substr($file, -3)) { continue; } $newestMTime = max($file->getMTime(), $newestMTime); } return $newestMTime < $timestamp; } public function serialize() { return serialize(array($this->resource, $this->pattern)); } public function unserialize($serialized) { list($this->resource, $this->pattern) = unserialize($serialized); } } PK]T!! Config/Resource/FileResource.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Resource; /** * FileResource represents a resource stored on the filesystem. * * The resource can be a file or a directory. * * @author Fabien Potencier */ class FileResource implements ResourceInterface, \Serializable { private $resource; /** * Constructor. * * @param string $resource The file path to the resource */ public function __construct($resource) { $this->resource = realpath($resource); } /** * Returns a string representation of the Resource. * * @return string A string representation of the Resource */ public function __toString() { return (string) $this->resource; } /** * Returns the resource tied to this Resource. * * @return mixed The resource */ public function getResource() { return $this->resource; } /** * Returns true if the resource has not been updated since the given timestamp. * * @param integer $timestamp The last time the resource was loaded * * @return Boolean true if the resource has not been updated, false otherwise */ public function isFresh($timestamp) { if (!file_exists($this->resource)) { return false; } return filemtime($this->resource) < $timestamp; } public function serialize() { return serialize($this->resource); } public function unserialize($serialized) { $this->resource = unserialize($serialized); } } PK]:a Config/ConfigCache.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Filesystem\Filesystem; /** * ConfigCache manages PHP cache files. * * When debug is enabled, it knows when to flush the cache * thanks to an array of ResourceInterface instances. * * @author Fabien Potencier */ class ConfigCache { private $debug; private $file; /** * Constructor. * * @param string $file The absolute cache path * @param Boolean $debug Whether debugging is enabled or not */ public function __construct($file, $debug) { $this->file = $file; $this->debug = (Boolean) $debug; } /** * Gets the cache file path. * * @return string The cache file path */ public function __toString() { return $this->file; } /** * Checks if the cache is still fresh. * * This method always returns true when debug is off and the * cache file exists. * * @return Boolean true if the cache is fresh, false otherwise */ public function isFresh() { if (!is_file($this->file)) { return false; } if (!$this->debug) { return true; } $metadata = $this->getMetaFile(); if (!is_file($metadata)) { return false; } $time = filemtime($this->file); $meta = unserialize(file_get_contents($metadata)); foreach ($meta as $resource) { if (!$resource->isFresh($time)) { return false; } } return true; } /** * Writes cache. * * @param string $content The content to write in the cache * @param ResourceInterface[] $metadata An array of ResourceInterface instances * * @throws \RuntimeException When cache file can't be wrote */ public function write($content, array $metadata = null) { $mode = 0666 & ~umask(); $filesystem = new Filesystem(); $filesystem->dumpFile($this->file, $content, null); @chmod($this->file, $mode); if (null !== $metadata && true === $this->debug) { $filesystem->dumpFile($this->getMetaFile(), serialize($metadata), null); @chmod($this->getMetaFile(), $mode); } } /** * Gets the meta file path. * * @return string The meta file path */ private function getMetaFile() { return $this->file.'.meta'; } } PK]`PPConfig/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * WinCacheClassLoader implements a wrapping autoloader cached in WinCache. * * It expects an object implementing a findFile method to find the file. This * allow using it as a wrapper around the other loaders of the component (the * ClassLoader and the UniversalClassLoader for instance) but also around any * other autoloader following this convention (the Composer one for instance) * * $loader = new ClassLoader(); * * // register classes with namespaces * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * $cachedLoader = new WinCacheClassLoader('my_prefix', $loader); * * // activate the cached autoloader * $cachedLoader->register(); * * // eventually deactivate the non-cached loader if it was registered previously * // to be sure to use the cached one. * $loader->unregister(); * * @author Fabien Potencier * @author Kris Wallsmith * @author Artem Ryzhkov */ class WinCacheClassLoader { private $prefix; /** * The class loader object being decorated. * * @var \Symfony\Component\ClassLoader\ClassLoader * A class loader object that implements the findFile() method. */ protected $decorated; /** * Constructor. * * @param string $prefix The WinCache namespace prefix to use. * @param object $decorated A class loader object that implements the findFile() method. * * @throws \RuntimeException * @throws \InvalidArgumentException */ public function __construct($prefix, $decorated) { if (!extension_loaded('wincache')) { throw new \RuntimeException('Unable to use WinCacheClassLoader as WinCache is not enabled.'); } if (!method_exists($decorated, 'findFile')) { throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); } $this->prefix = $prefix; $this->decorated = $decorated; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds a file by class name while caching lookups to WinCache. * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { if (false === $file = wincache_ucache_get($this->prefix.$class)) { wincache_ucache_set($this->prefix.$class, $file = $this->decorated->findFile($class), 0); } return $file; } /** * Passes through all unknown calls onto the decorated object. */ public function __call($method, $args) { return call_user_func_array(array($this->decorated, $method), $args); } } PK]S  ClassLoader/DebugClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * Autoloader checking if the class is really defined in the file found. * * The DebugClassLoader will wrap all registered autoloaders providing a * findFile method and will throw an exception if a file is found but does * not declare the class. * * @author Fabien Potencier * @author Christophe Coevoet * * @api * * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use the DebugClassLoader provided by the Debug component instead. */ class DebugClassLoader { private $classFinder; /** * Constructor. * * @param object $classFinder * * @api */ public function __construct($classFinder) { $this->classFinder = $classFinder; } /** * Gets the wrapped class loader. * * @return object a class loader instance */ public function getClassLoader() { return $this->classFinder; } /** * Replaces all autoloaders implementing a findFile method by a DebugClassLoader wrapper. */ public static function enable() { if (!is_array($functions = spl_autoload_functions())) { return; } foreach ($functions as $function) { spl_autoload_unregister($function); } foreach ($functions as $function) { if (is_array($function) && !$function[0] instanceof self && method_exists($function[0], 'findFile')) { $function = array(new static($function[0]), 'loadClass'); } spl_autoload_register($function); } } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Finds a file by class name * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { return $this->classFinder->findFile($class); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded * * @throws \RuntimeException */ public function loadClass($class) { if ($file = $this->classFinder->findFile($class)) { require $file; if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class, false))) { if (false !== strpos($class, '/')) { throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); } throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); } return true; } } } PK]AClassLoader/MapClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * A class loader that uses a mapping file to look up paths. * * @author Fabien Potencier */ class MapClassLoader { private $map = array(); /** * Constructor. * * @param array $map A map where keys are classes and values the absolute file path */ public function __construct(array $map) { $this->map = $map; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Loads the given class or interface. * * @param string $class The name of the class */ public function loadClass($class) { if (isset($this->map[$class])) { require $this->map[$class]; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|null The path, if found */ public function findFile($class) { if (isset($this->map[$class])) { return $this->map[$class]; } } } PK]a 'ClassLoader/ApcUniversalClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ApcUniversalClassLoader implements a "universal" autoloader cached in APC for PHP 5.3. * * It is able to load classes that use either: * * * The technical interoperability standards for PHP 5.3 namespaces and * class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md); * * * The PEAR naming convention for classes (http://pear.php.net/). * * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be * looked for in a list of locations to ease the vendoring of a sub-set of * classes for large projects. * * Example usage: * * require 'vendor/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; * require 'vendor/symfony/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; * * use Symfony\Component\ClassLoader\ApcUniversalClassLoader; * * $loader = new ApcUniversalClassLoader('apc.prefix.'); * * // register classes with namespaces * $loader->registerNamespaces(array( * 'Symfony\Component' => __DIR__.'/component', * 'Symfony' => __DIR__.'/framework', * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'), * )); * * // register a library using the PEAR naming convention * $loader->registerPrefixes(array( * 'Swift_' => __DIR__.'/Swift', * )); * * // activate the autoloader * $loader->register(); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * @author Fabien Potencier * @author Kris Wallsmith * * @api */ class ApcUniversalClassLoader extends UniversalClassLoader { private $prefix; /** * Constructor. * * @param string $prefix A prefix to create a namespace in APC * * @throws \RuntimeException * * @api */ public function __construct($prefix) { if (!extension_loaded('apc')) { throw new \RuntimeException('Unable to use ApcUniversalClassLoader as APC is not enabled.'); } $this->prefix = $prefix; } /** * Finds a file by class name while caching lookups to APC. * * @param string $class A class name to resolve to file * * @return string|null The path, if found */ public function findFile($class) { if (false === $file = apc_fetch($this->prefix.$class)) { apc_store($this->prefix.$class, $file = parent::findFile($class)); } return $file; } } PK]a.e"e"$ClassLoader/UniversalClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * UniversalClassLoader implements a "universal" autoloader for PHP 5.3. * * It is able to load classes that use either: * * * The technical interoperability standards for PHP 5.3 namespaces and * class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md); * * * The PEAR naming convention for classes (http://pear.php.net/). * * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be * looked for in a list of locations to ease the vendoring of a sub-set of * classes for large projects. * * Example usage: * * $loader = new UniversalClassLoader(); * * // register classes with namespaces * $loader->registerNamespaces(array( * 'Symfony\Component' => __DIR__.'/component', * 'Symfony' => __DIR__.'/framework', * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'), * )); * * // register a library using the PEAR naming convention * $loader->registerPrefixes(array( * 'Swift_' => __DIR__.'/Swift', * )); * * * // to enable searching the include path (e.g. for PEAR packages) * $loader->useIncludePath(true); * * // activate the autoloader * $loader->register(); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * @author Fabien Potencier * * @api */ class UniversalClassLoader { private $namespaces = array(); private $prefixes = array(); private $namespaceFallbacks = array(); private $prefixFallbacks = array(); private $useIncludePath = false; /** * Turns on searching the include for class files. Allows easy loading * of installed PEAR packages * * @param Boolean $useIncludePath */ public function useIncludePath($useIncludePath) { $this->useIncludePath = $useIncludePath; } /** * Can be used to check if the autoloader uses the include path to check * for classes. * * @return Boolean */ public function getUseIncludePath() { return $this->useIncludePath; } /** * Gets the configured namespaces. * * @return array A hash with namespaces as keys and directories as values */ public function getNamespaces() { return $this->namespaces; } /** * Gets the configured class prefixes. * * @return array A hash with class prefixes as keys and directories as values */ public function getPrefixes() { return $this->prefixes; } /** * Gets the directory(ies) to use as a fallback for namespaces. * * @return array An array of directories */ public function getNamespaceFallbacks() { return $this->namespaceFallbacks; } /** * Gets the directory(ies) to use as a fallback for class prefixes. * * @return array An array of directories */ public function getPrefixFallbacks() { return $this->prefixFallbacks; } /** * Registers the directory to use as a fallback for namespaces. * * @param array $dirs An array of directories * * @api */ public function registerNamespaceFallbacks(array $dirs) { $this->namespaceFallbacks = $dirs; } /** * Registers a directory to use as a fallback for namespaces. * * @param string $dir A directory */ public function registerNamespaceFallback($dir) { $this->namespaceFallbacks[] = $dir; } /** * Registers directories to use as a fallback for class prefixes. * * @param array $dirs An array of directories * * @api */ public function registerPrefixFallbacks(array $dirs) { $this->prefixFallbacks = $dirs; } /** * Registers a directory to use as a fallback for class prefixes. * * @param string $dir A directory */ public function registerPrefixFallback($dir) { $this->prefixFallbacks[] = $dir; } /** * Registers an array of namespaces * * @param array $namespaces An array of namespaces (namespaces as keys and locations as values) * * @api */ public function registerNamespaces(array $namespaces) { foreach ($namespaces as $namespace => $locations) { $this->namespaces[$namespace] = (array) $locations; } } /** * Registers a namespace. * * @param string $namespace The namespace * @param array|string $paths The location(s) of the namespace * * @api */ public function registerNamespace($namespace, $paths) { $this->namespaces[$namespace] = (array) $paths; } /** * Registers an array of classes using the PEAR naming convention. * * @param array $classes An array of classes (prefixes as keys and locations as values) * * @api */ public function registerPrefixes(array $classes) { foreach ($classes as $prefix => $locations) { $this->prefixes[$prefix] = (array) $locations; } } /** * Registers a set of classes using the PEAR naming convention. * * @param string $prefix The classes prefix * @param array|string $paths The location(s) of the classes * * @api */ public function registerPrefix($prefix, $paths) { $this->prefixes[$prefix] = (array) $paths; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not * * @api */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|null The path, if found */ public function findFile($class) { if (false !== $pos = strrpos($class, '\\')) { // namespaced class name $namespace = substr($class, 0, $pos); $className = substr($class, $pos + 1); $normalizedClass = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; foreach ($this->namespaces as $ns => $dirs) { if (0 !== strpos($namespace, $ns)) { continue; } foreach ($dirs as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } foreach ($this->namespaceFallbacks as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } else { // PEAR-like class name $normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; foreach ($this->prefixes as $prefix => $dirs) { if (0 !== strpos($class, $prefix)) { continue; } foreach ($dirs as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } foreach ($this->prefixFallbacks as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } if ($this->useIncludePath && $file = stream_resolve_include_path($normalizedClass)) { return $file; } } } PK]?wy !ClassLoader/ClassMapGenerator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ClassMapGenerator * * @author Gyula Sallai */ class ClassMapGenerator { /** * Generate a class map file * * @param array|string $dirs Directories or a single path to search in * @param string $file The name of the class map file */ public static function dump($dirs, $file) { $dirs = (array) $dirs; $maps = array(); foreach ($dirs as $dir) { $maps = array_merge($maps, static::createMap($dir)); } file_put_contents($file, sprintf('isFile()) { continue; } $path = $file->getRealPath(); if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') { continue; } $classes = self::findClasses($path); foreach ($classes as $class) { $map[$class] = $path; } } return $map; } /** * Extract the classes in the given file * * @param string $path The file to check * * @return array The found classes */ private static function findClasses($path) { $contents = file_get_contents($path); $tokens = token_get_all($contents); $T_TRAIT = version_compare(PHP_VERSION, '5.4', '<') ? -1 : T_TRAIT; $classes = array(); $namespace = ''; for ($i = 0, $max = count($tokens); $i < $max; $i++) { $token = $tokens[$i]; if (is_string($token)) { continue; } $class = ''; switch ($token[0]) { case T_NAMESPACE: $namespace = ''; // If there is a namespace, extract it while (($t = $tokens[++$i]) && is_array($t)) { if (in_array($t[0], array(T_STRING, T_NS_SEPARATOR))) { $namespace .= $t[1]; } } $namespace .= '\\'; break; case T_CLASS: case T_INTERFACE: case $T_TRAIT: // Find the classname while (($t = $tokens[++$i]) && is_array($t)) { if (T_STRING === $t[0]) { $class .= $t[1]; } elseif ($class !== '' && T_WHITESPACE == $t[0]) { break; } } $classes[] = ltrim($namespace.$class, '\\'); break; default: break; } } return $classes; } } PK]v . .%ClassLoader/ClassCollectionLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ClassCollectionLoader. * * @author Fabien Potencier */ class ClassCollectionLoader { private static $loaded; private static $seen; private static $useTokenizer = true; /** * Loads a list of classes and caches them in one big file. * * @param array $classes An array of classes to load * @param string $cacheDir A cache directory * @param string $name The cache name prefix * @param Boolean $autoReload Whether to flush the cache when the cache is stale or not * @param Boolean $adaptive Whether to remove already declared classes or not * @param string $extension File extension of the resulting file * * @throws \InvalidArgumentException When class can't be loaded */ public static function load($classes, $cacheDir, $name, $autoReload, $adaptive = false, $extension = '.php') { // each $name can only be loaded once per PHP process if (isset(self::$loaded[$name])) { return; } self::$loaded[$name] = true; $declared = array_merge(get_declared_classes(), get_declared_interfaces()); if (function_exists('get_declared_traits')) { $declared = array_merge($declared, get_declared_traits()); } if ($adaptive) { // don't include already declared classes $classes = array_diff($classes, $declared); // the cache is different depending on which classes are already declared $name = $name.'-'.substr(hash('sha256', implode('|', $classes)), 0, 5); } $classes = array_unique($classes); $cache = $cacheDir.'/'.$name.$extension; // auto-reload $reload = false; if ($autoReload) { $metadata = $cache.'.meta'; if (!is_file($metadata) || !is_file($cache)) { $reload = true; } else { $time = filemtime($cache); $meta = unserialize(file_get_contents($metadata)); sort($meta[1]); sort($classes); if ($meta[1] != $classes) { $reload = true; } else { foreach ($meta[0] as $resource) { if (!is_file($resource) || filemtime($resource) > $time) { $reload = true; break; } } } } } if (!$reload && is_file($cache)) { require_once $cache; return; } $files = array(); $content = ''; foreach (self::getOrderedClasses($classes) as $class) { if (in_array($class->getName(), $declared)) { continue; } $files[] = $class->getFileName(); $c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($class->getFileName())); // fakes namespace declaration for global code if (!$class->inNamespace()) { $c = "\nnamespace\n{\n".$c."\n}\n"; } $c = self::fixNamespaceDeclarations('getName()])) { return array(); } self::$seen[$class->getName()] = true; $classes = array($class); $parent = $class; while (($parent = $parent->getParentClass()) && $parent->isUserDefined() && !isset(self::$seen[$parent->getName()])) { self::$seen[$parent->getName()] = true; array_unshift($classes, $parent); } $traits = array(); if (function_exists('get_declared_traits')) { foreach ($classes as $c) { foreach (self::resolveDependencies(self::computeTraitDeps($c), $c) as $trait) { if ($trait !== $c) { $traits[] = $trait; } } } } return array_merge(self::getInterfaces($class), $traits, $classes); } private static function getInterfaces(\ReflectionClass $class) { $classes = array(); foreach ($class->getInterfaces() as $interface) { $classes = array_merge($classes, self::getInterfaces($interface)); } if ($class->isUserDefined() && $class->isInterface() && !isset(self::$seen[$class->getName()])) { self::$seen[$class->getName()] = true; $classes[] = $class; } return $classes; } private static function computeTraitDeps(\ReflectionClass $class) { $traits = $class->getTraits(); $deps = array($class->getName() => $traits); while ($trait = array_pop($traits)) { if ($trait->isUserDefined() && !isset(self::$seen[$trait->getName()])) { self::$seen[$trait->getName()] = true; $traitDeps = $trait->getTraits(); $deps[$trait->getName()] = $traitDeps; $traits = array_merge($traits, $traitDeps); } } return $deps; } /** * Dependencies resolution. * * This function does not check for circular dependencies as it should never * occur with PHP traits. * * @param array $tree The dependency tree * @param \ReflectionClass $node The node * @param \ArrayObject $resolved An array of already resolved dependencies * @param \ArrayObject $unresolved An array of dependencies to be resolved * * @return \ArrayObject The dependencies for the given node * * @throws \RuntimeException if a circular dependency is detected */ private static function resolveDependencies(array $tree, $node, \ArrayObject $resolved = null, \ArrayObject $unresolved = null) { if (null === $resolved) { $resolved = new \ArrayObject(); } if (null === $unresolved) { $unresolved = new \ArrayObject(); } $nodeName = $node->getName(); $unresolved[$nodeName] = $node; foreach ($tree[$nodeName] as $dependency) { if (!$resolved->offsetExists($dependency->getName())) { self::resolveDependencies($tree, $dependency, $resolved, $unresolved); } } $resolved[$nodeName] = $node; unset($unresolved[$nodeName]); return $resolved; } } PK]lOݫClassLoader/ApcClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ApcClassLoader implements a wrapping autoloader cached in APC for PHP 5.3. * * It expects an object implementing a findFile method to find the file. This * allow using it as a wrapper around the other loaders of the component (the * ClassLoader and the UniversalClassLoader for instance) but also around any * other autoloader following this convention (the Composer one for instance) * * $loader = new ClassLoader(); * * // register classes with namespaces * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * $cachedLoader = new ApcClassLoader('my_prefix', $loader); * * // activate the cached autoloader * $cachedLoader->register(); * * // eventually deactivate the non-cached loader if it was registered previously * // to be sure to use the cached one. * $loader->unregister(); * * @author Fabien Potencier * @author Kris Wallsmith * * @api */ class ApcClassLoader { private $prefix; /** * The class loader object being decorated. * * @var \Symfony\Component\ClassLoader\ClassLoader * A class loader object that implements the findFile() method. */ protected $decorated; /** * Constructor. * * @param string $prefix The APC namespace prefix to use. * @param object $decorated A class loader object that implements the findFile() method. * * @throws \RuntimeException * @throws \InvalidArgumentException * * @api */ public function __construct($prefix, $decorated) { if (!extension_loaded('apc')) { throw new \RuntimeException('Unable to use ApcClassLoader as APC is not enabled.'); } if (!method_exists($decorated, 'findFile')) { throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); } $this->prefix = $prefix; $this->decorated = $decorated; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds a file by class name while caching lookups to APC. * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { if (false === $file = apc_fetch($this->prefix.$class)) { apc_store($this->prefix.$class, $file = $this->decorated->findFile($class)); } return $file; } /** * Passes through all unknown calls onto the decorated object. */ public function __call($method, $args) { return call_user_func_array(array($this->decorated, $method), $args); } } PK]PЩ !ClassLoader/XcacheClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * XcacheClassLoader implements a wrapping autoloader cached in Xcache for PHP 5.3. * * It expects an object implementing a findFile method to find the file. This * allows using it as a wrapper around the other loaders of the component (the * ClassLoader and the UniversalClassLoader for instance) but also around any * other autoloader following this convention (the Composer one for instance) * * $loader = new ClassLoader(); * * // register classes with namespaces * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * $cachedLoader = new XcacheClassLoader('my_prefix', $loader); * * // activate the cached autoloader * $cachedLoader->register(); * * // eventually deactivate the non-cached loader if it was registered previously * // to be sure to use the cached one. * $loader->unregister(); * * @author Fabien Potencier * @author Kris Wallsmith * @author Kim Hemsø Rasmussen * * @api */ class XcacheClassLoader { private $prefix; private $classFinder; /** * Constructor. * * @param string $prefix A prefix to create a namespace in Xcache * @param object $classFinder An object that implements findFile() method. * * @throws \RuntimeException * @throws \InvalidArgumentException * * @api */ public function __construct($prefix, $classFinder) { if (!extension_loaded('Xcache')) { throw new \RuntimeException('Unable to use XcacheClassLoader as Xcache is not enabled.'); } if (!method_exists($classFinder, 'findFile')) { throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); } $this->prefix = $prefix; $this->classFinder = $classFinder; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds a file by class name while caching lookups to Xcache. * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { if (xcache_isset($this->prefix.$class)) { $file = xcache_get($this->prefix.$class); } else { $file = $this->classFinder->findFile($class); xcache_set($this->prefix.$class, $file); } return $file; } } PK]w!)))ClassLoader/DebugUniversalClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * Checks that the class is actually declared in the included file. * * @author Fabien Potencier */ class DebugUniversalClassLoader extends UniversalClassLoader { /** * Replaces all regular UniversalClassLoader instances by a DebugUniversalClassLoader ones. */ public static function enable() { if (!is_array($functions = spl_autoload_functions())) { return; } foreach ($functions as $function) { spl_autoload_unregister($function); } foreach ($functions as $function) { if (is_array($function) && $function[0] instanceof UniversalClassLoader) { $loader = new static(); $loader->registerNamespaceFallbacks($function[0]->getNamespaceFallbacks()); $loader->registerPrefixFallbacks($function[0]->getPrefixFallbacks()); $loader->registerNamespaces($function[0]->getNamespaces()); $loader->registerPrefixes($function[0]->getPrefixes()); $loader->useIncludePath($function[0]->getUseIncludePath()); $function[0] = $loader; } spl_autoload_register($function); } } /** * {@inheritDoc} */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class, false))) { throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); } } } } PK]v'ClassLoader/ClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ClassLoader implements an PSR-0 class loader * * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md * * $loader = new ClassLoader(); * * // register classes with namespaces * $loader->addPrefix('Symfony\Component', __DIR__.'/component'); * $loader->addPrefix('Symfony', __DIR__.'/framework'); * * // activate the autoloader * $loader->register(); * * // to enable searching the include path (e.g. for PEAR packages) * $loader->setUseIncludePath(true); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * @author Fabien Potencier * @author Jordi Boggiano */ class ClassLoader { private $prefixes = array(); private $fallbackDirs = array(); private $useIncludePath = false; /** * Returns prefixes. * * @return array */ public function getPrefixes() { return $this->prefixes; } /** * Returns fallback directories. * * @return array */ public function getFallbackDirs() { return $this->fallbackDirs; } /** * Adds prefixes. * * @param array $prefixes Prefixes to add */ public function addPrefixes(array $prefixes) { foreach ($prefixes as $prefix => $path) { $this->addPrefix($prefix, $path); } } /** * Registers a set of classes * * @param string $prefix The classes prefix * @param array|string $paths The location(s) of the classes */ public function addPrefix($prefix, $paths) { if (!$prefix) { foreach ((array) $paths as $path) { $this->fallbackDirs[] = $path; } return; } if (isset($this->prefixes[$prefix])) { $this->prefixes[$prefix] = array_merge( $this->prefixes[$prefix], (array) $paths ); } else { $this->prefixes[$prefix] = (array) $paths; } } /** * Turns on searching the include for class files. * * @param Boolean $useIncludePath */ public function setUseIncludePath($useIncludePath) { $this->useIncludePath = $useIncludePath; } /** * Can be used to check if the autoloader uses the include path to check * for classes. * * @return Boolean */ public function getUseIncludePath() { return $this->useIncludePath; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|null The path, if found */ public function findFile($class) { if (false !== $pos = strrpos($class, '\\')) { // namespaced class name $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR; $className = substr($class, $pos + 1); } else { // PEAR-like class name $classPath = null; $className = $class; } $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; foreach ($this->prefixes as $prefix => $dirs) { if ($class === strstr($class, $prefix)) { foreach ($dirs as $dir) { if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { return $dir.DIRECTORY_SEPARATOR.$classPath; } } } } foreach ($this->fallbackDirs as $dir) { if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { return $dir.DIRECTORY_SEPARATOR.$classPath; } } if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) { return $file; } } } PK]"KUUClassLoader/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * A form extension with preloaded types, type exceptions and type guessers. * * @author Bernhard Schussek */ class PreloadedExtension implements FormExtensionInterface { /** * @var array */ private $types = array(); /** * @var array */ private $typeExtensions = array(); /** * @var FormTypeGuesserInterface */ private $typeGuesser; /** * Creates a new preloaded extension. * * @param FormTypeInterface[] $types The types that the extension should support. * @param array[FormTypeExtensionInterface[]] typeExtensions The type extensions that the extension should support. * @param FormTypeGuesserInterface|null $typeGuesser The guesser that the extension should support. */ public function __construct(array $types, array $typeExtensions, FormTypeGuesserInterface $typeGuesser = null) { $this->types = $types; $this->typeExtensions = $typeExtensions; $this->typeGuesser = $typeGuesser; } /** * {@inheritdoc} */ public function getType($name) { if (!isset($this->types[$name])) { throw new InvalidArgumentException(sprintf('The type "%s" can not be loaded by this extension', $name)); } return $this->types[$name]; } /** * {@inheritdoc} */ public function hasType($name) { return isset($this->types[$name]); } /** * {@inheritdoc} */ public function getTypeExtensions($name) { return isset($this->typeExtensions[$name]) ? $this->typeExtensions[$name] : array(); } /** * {@inheritdoc} */ public function hasTypeExtensions($name) { return !empty($this->typeExtensions[$name]); } /** * {@inheritdoc} */ public function getTypeGuesser() { return $this->typeGuesser; } } PK]*Form/ResolvedFormType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\OptionsResolver\OptionsResolver; /** * A wrapper for a form type and its extensions. * * @author Bernhard Schussek */ class ResolvedFormType implements ResolvedFormTypeInterface { /** * @var FormTypeInterface */ private $innerType; /** * @var FormTypeExtensionInterface[] */ private $typeExtensions; /** * @var ResolvedFormTypeInterface|null */ private $parent; /** * @var OptionsResolver */ private $optionsResolver; public function __construct(FormTypeInterface $innerType, array $typeExtensions = array(), ResolvedFormTypeInterface $parent = null) { if (!preg_match('/^[a-z0-9_]*$/i', $innerType->getName())) { throw new InvalidArgumentException(sprintf( 'The "%s" form type name ("%s") is not valid. Names must only contain letters, numbers, and "_".', get_class($innerType), $innerType->getName() )); } foreach ($typeExtensions as $extension) { if (!$extension instanceof FormTypeExtensionInterface) { throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface'); } } $this->innerType = $innerType; $this->typeExtensions = $typeExtensions; $this->parent = $parent; } /** * {@inheritdoc} */ public function getName() { return $this->innerType->getName(); } /** * {@inheritdoc} */ public function getParent() { return $this->parent; } /** * {@inheritdoc} */ public function getInnerType() { return $this->innerType; } /** * {@inheritdoc} */ public function getTypeExtensions() { // BC if ($this->innerType instanceof AbstractType) { return $this->innerType->getExtensions(); } return $this->typeExtensions; } /** * {@inheritdoc} */ public function createBuilder(FormFactoryInterface $factory, $name, array $options = array()) { $options = $this->getOptionsResolver()->resolve($options); // Should be decoupled from the specific option at some point $dataClass = isset($options['data_class']) ? $options['data_class'] : null; $builder = $this->newBuilder($name, $dataClass, $factory, $options); $builder->setType($this); return $builder; } /** * {@inheritdoc} */ public function createView(FormInterface $form, FormView $parent = null) { return $this->newView($parent); } /** * Configures a form builder for the type hierarchy. * * @param FormBuilderInterface $builder The builder to configure. * @param array $options The options used for the configuration. */ public function buildForm(FormBuilderInterface $builder, array $options) { if (null !== $this->parent) { $this->parent->buildForm($builder, $options); } $this->innerType->buildForm($builder, $options); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->buildForm($builder, $options); } } /** * Configures a form view for the type hierarchy. * * This method is called before the children of the view are built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function buildView(FormView $view, FormInterface $form, array $options) { if (null !== $this->parent) { $this->parent->buildView($view, $form, $options); } $this->innerType->buildView($view, $form, $options); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->buildView($view, $form, $options); } } /** * Finishes a form view for the type hierarchy. * * This method is called after the children of the view have been built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function finishView(FormView $view, FormInterface $form, array $options) { if (null !== $this->parent) { $this->parent->finishView($view, $form, $options); } $this->innerType->finishView($view, $form, $options); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->finishView($view, $form, $options); } } /** * Returns the configured options resolver used for this type. * * @return \Symfony\Component\OptionsResolver\OptionsResolverInterface The options resolver. */ public function getOptionsResolver() { if (null === $this->optionsResolver) { if (null !== $this->parent) { $this->optionsResolver = clone $this->parent->getOptionsResolver(); } else { $this->optionsResolver = new OptionsResolver(); } $this->innerType->setDefaultOptions($this->optionsResolver); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->setDefaultOptions($this->optionsResolver); } } return $this->optionsResolver; } /** * Creates a new builder instance. * * Override this method if you want to customize the builder class. * * @param string $name The name of the builder. * @param string $dataClass The data class. * @param FormFactoryInterface $factory The current form factory. * @param array $options The builder options. * * @return FormBuilderInterface The new builder instance. */ protected function newBuilder($name, $dataClass, FormFactoryInterface $factory, array $options) { if ($this->innerType instanceof ButtonTypeInterface) { return new ButtonBuilder($name, $options); } if ($this->innerType instanceof SubmitButtonTypeInterface) { return new SubmitButtonBuilder($name, $options); } return new FormBuilder($name, $dataClass, new EventDispatcher(), $factory, $options); } /** * Creates a new view instance. * * Override this method if you want to customize the view class. * * @param FormView|null $parent The parent view, if available. * * @return FormView A new view instance. */ protected function newView(FormView $parent = null) { return new FormView($parent); } } PK]xfh..$Form/Resources/config/validation.xmlnu[ PK]--Form/Resources/translations/validators.ru.xlfnu[ This form should not contain extra fields. Эта форма не должна содержать дополнительных полей. The uploaded file was too large. Please try to upload a smaller file. Загруженный файл слишком большой. Пожалуйста, попробуйте загрузить файл меньшего размера. The CSRF token is invalid. Please try to resubmit the form. CSRF значение недопустимо. Пожалуйста, попробуйте повторить отправку формы. PK] -Form/Resources/translations/validators.pt.xlfnu[ This form should not contain extra fields. Este formulário não deveria conter campos extra. The uploaded file was too large. Please try to upload a smaller file. O arquivo enviado é muito grande. Por favor, tente enviar um ficheiro mais pequeno. The CSRF token is invalid. Please try to resubmit the form. O token CSRF é inválido. Por favor submeta o formulário novamente. PK]n-Form/Resources/translations/validators.en.xlfnu[ This form should not contain extra fields. This form should not contain extra fields. The uploaded file was too large. Please try to upload a smaller file. The uploaded file was too large. Please try to upload a smaller file. The CSRF token is invalid. Please try to resubmit the form. The CSRF token is invalid. Please try to resubmit the form. PK]NP\-Form/Resources/translations/validators.he.xlfnu[ This form should not contain extra fields. הטופס לא צריך להכיל שדות נוספים. The uploaded file was too large. Please try to upload a smaller file. הקובץ שהועלה גדול מדי. נסה להעלות קובץ קטן יותר. The CSRF token is invalid. אסימון CSRF אינו חוקי. PK]-Form/Resources/translations/validators.mn.xlfnu[ This form should not contain extra fields. Форм нэмэлт талбар багтаах боломжгүй. The uploaded file was too large. Please try to upload a smaller file. Upload хийсэн файл хэтэрхий том байна. Бага хэмжээтэй файл оруулна уу. The CSRF token is invalid. Please try to resubmit the form. CSRF token буруу байна. Формоо дахин илгээнэ үү. PK]:-Form/Resources/translations/validators.pl.xlfnu[ This form should not contain extra fields. Ten formularz nie powinien zawierać dodatkowych pól. The uploaded file was too large. Please try to upload a smaller file. Wgrany plik był za duży. Proszę spróbować wgrać mniejszy plik. The CSRF token is invalid. Please try to resubmit the form. Token CSRF jest nieprawidłowy. Proszę spróbować wysłać formularz ponownie. PK]5-Form/Resources/translations/validators.sl.xlfnu[ This form should not contain extra fields. Ta obrazec ne sme vsebovati dodatnih polj. The uploaded file was too large. Please try to upload a smaller file. Naložena datoteka je prevelika. Prosimo, poizkusite naložiti manjšo. The CSRF token is invalid. Please try to resubmit the form. CSRF vrednost je napačna. Prosimo, ponovno pošljite obrazec. PK]_Π-Form/Resources/translations/validators.el.xlfnu[ This form should not contain extra fields. Αυτή η φόρμα δεν πρέπει να περιέχει επιπλέον πεδία. The uploaded file was too large. Please try to upload a smaller file. Το αρχείο είναι πολύ μεγάλο. Παρακαλούμε προσπαθήστε να ανεβάσετε ένα μικρότερο αρχείο. The CSRF token is invalid. Please try to resubmit the form. Το CSRF token δεν είναι έγκυρο. Παρακαλούμε δοκιμάστε να υποβάλετε τη φόρμα ξανά. PK]X-Form/Resources/translations/validators.da.xlfnu[ This form should not contain extra fields. Feltgruppen må ikke indeholde ekstra felter. The uploaded file was too large. Please try to upload a smaller file. Den oploadede fil var for stor. Opload venligst en mindre fil. The CSRF token is invalid. Please try to resubmit the form. CSRF nøglen er ugyldig. PK]-Form/Resources/translations/validators.fi.xlfnu[ This field group should not contain extra fields. Tämä kenttäryhmä ei voi sisältää ylimääräisiä kenttiä. The uploaded file was too large. Please try to upload a smaller file. Ladattu tiedosto on liian iso. Ole hyvä ja lataa pienempi tiedosto. The CSRF token is invalid. Please try to resubmit the form. CSRF tarkiste on virheellinen. Olen hyvä ja yritä lähettää lomake uudestaan. PK]4@0Form/Resources/translations/validators.pt_BR.xlfnu[ This form should not contain extra fields. Este formulário não deve conter campos adicionais. The uploaded file was too large. Please try to upload a smaller file. O arquivo enviado é muito grande. Por favor, tente enviar um arquivo menor. The CSRF token is invalid. Please try to resubmit the form. O token CSRF é inválido. Por favor, tente reenviar o formulário. PK]Hq-Form/Resources/translations/validators.lt.xlfnu[ This form should not contain extra fields. Forma negali turėti papildomų laukų. The uploaded file was too large. Please try to upload a smaller file. Įkelta byla yra per didelė. bandykite įkelti mažesnę. The CSRF token is invalid. Please try to resubmit the form. CSRF kodas nepriimtinas. Bandykite siųsti formos užklausą dar kartą. PK]O-Form/Resources/translations/validators.nl.xlfnu[ This form should not contain extra fields. Dit formulier mag geen extra velden bevatten. The uploaded file was too large. Please try to upload a smaller file. Het geüploade bestand is te groot. Probeer een kleiner bestand te uploaden. The CSRF token is invalid. Please try to resubmit the form. De CSRF-token is ongeldig. Probeer het formulier opnieuw te versturen. PK]s>ll-Form/Resources/translations/validators.sv.xlfnu[ This form should not contain extra fields. Formuläret kan inte innehålla extra fält. The uploaded file was too large. Please try to upload a smaller file. Den uppladdade filen var för stor. Försök ladda upp en mindre fil. The CSRF token is invalid. CSRF-symbolen är inte giltig. PK]A4-Form/Resources/translations/validators.gl.xlfnu[ This form should not contain extra fields. Este formulario non debería conter campos adicionais. The uploaded file was too large. Please try to upload a smaller file. O arquivo subido é demasiado grande. Por favor, suba un arquivo máis pequeno. The CSRF token is invalid. Please try to resubmit the form. O token CSRF non é válido. Por favor, probe a enviar novamente o formulario. PK]y99-Form/Resources/translations/validators.hy.xlfnu[ This form should not contain extra fields. Այս ձևը չպետք է պարունակի լրացուցիչ տողեր. The uploaded file was too large. Please try to upload a smaller file. Վերբեռնված ֆայլը չափազանց մեծ է: Խնդրվում է վերբեռնել ավելի փոքր չափսի ֆայլ. The CSRF token is invalid. Please try to resubmit the form. CSRF արժեքը անթույլատրելի է: Փորձեք նորից ուղարկել ձևը. PK]TI-Form/Resources/translations/validators.de.xlfnu[ This form should not contain extra fields. Dieses Formular sollte keine zusätzlichen Felder enthalten. The uploaded file was too large. Please try to upload a smaller file. Die hochgeladene Datei ist zu groß. Versuchen Sie bitte eine kleinere Datei hochzuladen. The CSRF token is invalid. Please try to resubmit the form. Der CSRF-Token ist ungültig. Versuchen Sie bitte das Formular erneut zu senden. PK]誫-Form/Resources/translations/validators.sk.xlfnu[ This form should not contain extra fields. Polia by nemali obsahovať ďalšie prvky. The uploaded file was too large. Please try to upload a smaller file. Odoslaný súbor je príliš veľký. Prosím odošlite súbor s menšou veľkosťou. The CSRF token is invalid. Please try to resubmit the form. CSRF token je neplatný. Prosím skúste znovu odoslať formulár. PK]%-Form/Resources/translations/validators.lv.xlfnu[ This form should not contain extra fields. Šajā veidlapā nevajadzētu būt papildus ievades laukiem. The uploaded file was too large. Please try to upload a smaller file. Augšupielādētā faila izmērs bija par lielu. Lūdzu mēģiniet augšupielādēt mazāka izmēra failu. The CSRF token is invalid. Please try to resubmit the form. Dotais CSRF talons nav derīgs. Lūdzu mēģiniet vēlreiz iesniegt veidlapu. PK] -Form/Resources/translations/validators.cs.xlfnu[ This form should not contain extra fields. Tato skupina polí nesmí obsahovat další pole. The uploaded file was too large. Please try to upload a smaller file. Nahraný soubor je příliš velký. Nahrajte prosím menší soubor. The CSRF token is invalid. Please try to resubmit the form. CSRF token je neplatný. Zkuste prosím znovu odeslat formulář. PK]WgUugg-Form/Resources/translations/validators.nb.xlfnu[ This form should not contain extra fields. Feltgruppen må ikke inneholde ekstra felter. The uploaded file was too large. Please try to upload a smaller file. Den opplastede file var for stor. Vennligst last opp en mindre fil. The CSRF token is invalid. CSRF nøkkelen er ugyldig. PK]8,:0Form/Resources/translations/validators.zh_CN.xlfnu[ This form should not contain extra fields. 该表单中不可有额外字段. The uploaded file was too large. Please try to upload a smaller file. 上传文件太大, 请重新尝试上传一个较小的文件. The CSRF token is invalid. Please try to resubmit the form. CSRF 验证符无效, 请重新提交. PK] b8-Form/Resources/translations/validators.hr.xlfnu[ This form should not contain extra fields. Ovaj obrazac ne smije sadržavati dodatna polja. The uploaded file was too large. Please try to upload a smaller file. Prenesena datoteka je prevelika. Molim pokušajte prenijeti manju datoteku. The CSRF token is invalid. Please try to resubmit the form. CSRF vrijednost nije ispravna. Pokušajte ponovo poslati obrazac. PK]be@-Form/Resources/translations/validators.hu.xlfnu[ This form should not contain extra fields. Ez a mezőcsoport nem tartalmazhat extra mezőket. The uploaded file was too large. Please try to upload a smaller file. A feltöltött fájl túl nagy. Kérem próbáljon egy kisebb fájlt feltölteni. The CSRF token is invalid. Please try to resubmit the form. Érvénytelen CSRF token. Kérem próbálja újra elküldeni az űrlapot. PK]္o332Form/Resources/translations/validators.sr_Cyrl.xlfnu[ This form should not contain extra fields. Овај формулар не треба да садржи додатна поља. The uploaded file was too large. Please try to upload a smaller file. Отпремљена датотека је била превелика. Молим покушајте отпремање мање датотеке. The CSRF token is invalid. Please try to resubmit the form. CSRF вредност је невалидна. Покушајте поново. PK]-Form/Resources/translations/validators.ja.xlfnu[ This form should not contain extra fields. フィールドグループに追加のフィールドを含んではなりません。 The uploaded file was too large. Please try to upload a smaller file. アップロードされたファイルが大きすぎます。小さなファイルで再度アップロードしてください。 The CSRF token is invalid. CSRFトークンが無効です。 PK]|C-Form/Resources/translations/validators.ar.xlfnu[ This form should not contain extra fields. هذا النموذج يجب الا يحتوى على اى حقول اضافية. The uploaded file was too large. Please try to upload a smaller file. مساحة الملف المرسل كبيرة. من فضلك حاول ارسال ملف اصغر. The CSRF token is invalid. Please try to resubmit the form. قيمة رمز الموقع غير صحيحة. من فضلك اعد ارسال النموذج. PK]*{-Form/Resources/translations/validators.lb.xlfnu[ This form should not contain extra fields. Dës Feldergrupp sollt keng zousätzlech Felder enthalen. The uploaded file was too large. Please try to upload a smaller file. De geschécktene Fichier ass ze grouss. Versicht wann ech gelift ee méi klenge Fichier eropzelueden. The CSRF token is invalid. Please try to resubmit the form. Den CSRF-Token ass ongëlteg. Versicht wann ech gelift de Formulaire nach eng Kéier ze schécken. PK]0h-Form/Resources/translations/validators.es.xlfnu[ This form should not contain extra fields. Este formulario no debería contener campos adicionales. The uploaded file was too large. Please try to upload a smaller file. El archivo subido es demasiado grande. Por favor, suba un archivo más pequeño. The CSRF token is invalid. Please try to resubmit the form. El token CSRF no es válido. Por favor, pruebe de enviar nuevamente el formulario. PK]Ed-Form/Resources/translations/validators.ro.xlfnu[ This form should not contain extra fields. Aceast formular nu ar trebui să conțină câmpuri suplimentare. The uploaded file was too large. Please try to upload a smaller file. Fișierul încărcat a fost prea mare. Vă rugăm sa încărcați un fișier mai mic. The CSRF token is invalid. Please try to resubmit the form. Token-ul CSRF este invalid. Vă rugăm să trimiteți formularul incă o dată. PK]<yy-Form/Resources/translations/validators.uk.xlfnu[ This form should not contain extra fields. Ця форма не повинна містити додаткових полів. The uploaded file was too large. Please try to upload a smaller file. Завантажений файл занадто великий. Будь-ласка, спробуйте завантажити файл меншого розміру. The CSRF token is invalid. Please try to resubmit the form. CSRF значення недопустиме. Будь-ласка, спробуйте відправити форму знову. PK]_8-Form/Resources/translations/validators.fr.xlfnu[ This form should not contain extra fields. Ce formulaire ne doit pas contenir des champs supplémentaires. The uploaded file was too large. Please try to upload a smaller file. Le fichier téléchargé est trop volumineux. Merci d'essayer d'envoyer un fichier plus petit. The CSRF token is invalid. Please try to resubmit the form. Le jeton CSRF est invalide. Veuillez renvoyer le formulaire. PK]!aZ-Form/Resources/translations/validators.it.xlfnu[ This form should not contain extra fields. Questo form non dovrebbe contenere nessun campo extra. The uploaded file was too large. Please try to upload a smaller file. Il file caricato è troppo grande. Per favore caricare un file più piccolo. The CSRF token is invalid. Please try to resubmit the form. Il token CSRF non è valido. Provare a reinviare il form. PK] !-Form/Resources/translations/validators.ca.xlfnu[ This form should not contain extra fields. Aquest formulari no hauria de contenir camps addicionals. The uploaded file was too large. Please try to upload a smaller file. L'arxiu pujat és massa gran. Per favor, pugi un arxiu més petit. The CSRF token is invalid. Please try to resubmit the form. El token CSRF no és vàlid. Per favor, provi d'enviar novament el formulari. PK]3Ե^^-Form/Resources/translations/validators.bg.xlfnu[ This form should not contain extra fields. Тази форма не трябва да съдържа допълнителни полета. The uploaded file was too large. Please try to upload a smaller file. Каченият файл е твърде голям. Моля, опитайте да качите по-малък файл. The CSRF token is invalid. Please try to resubmit the form. Невалиден CSRF токен. Моля, опитайте да изпратите формата отново. PK]ٻ||-Form/Resources/translations/validators.eu.xlfnu[ This form should not contain extra fields. Formulario honek ez luke aparteko eremurik eduki behar. The uploaded file was too large. Please try to upload a smaller file. Igotako fitxategia handiegia da. Mesedez saiatu fitxategi txikiago bat igotzen. The CSRF token is invalid. CSFR tokena ez da egokia. PK]q-Form/Resources/translations/validators.id.xlfnu[ This form should not contain extra fields. Gabungan kolom tidak boleh mengandung kolom tambahan. The uploaded file was too large. Please try to upload a smaller file. Berkas yang di unggah terlalu besar. Silahkan coba unggah berkas yang lebih kecil. The CSRF token is invalid. Please try to resubmit the form. CSRF-Token tidak sah. Silahkan coba kirim ulang formulir. PK]S*-Form/Resources/translations/validators.et.xlfnu[ This form should not contain extra fields. Väljade grupp ei tohiks sisalda lisaväljasid. The uploaded file was too large. Please try to upload a smaller file. Üleslaaditud fail oli liiga suur. Palun proovi uuesti väiksema failiga. The CSRF token is invalid. Please try to resubmit the form. CSRF-märgis on vigane. Palun proovi vormi uuesti esitada. PK]V5-Form/Resources/translations/validators.fa.xlfnu[ This form should not contain extra fields. این فرم نباید فیلد اضافی داشته باشد. The uploaded file was too large. Please try to upload a smaller file. فایل بارگذاری شده بسیار بزرگ است. لطفا فایل کوچکتری را بارگزاری کنید. The CSRF token is invalid. Please try to resubmit the form. مقدار CSRF نامعتبر است. لطفا فرم را مجددا ارسال فرمایید.. PK]r2Form/Resources/translations/validators.sr_Latn.xlfnu[ This form should not contain extra fields. Ovaj formular ne treba da sadrži dodatna polja. The uploaded file was too large. Please try to upload a smaller file. Otpremljena datoteka je bila prevelika. Molim pokušajte otpremanje manje datoteke. The CSRF token is invalid. Please try to resubmit the form. CSRF vrednost je nevalidna. Pokušajte ponovo. PK]&"̰TTForm/FormConfigBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\PropertyPathInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\ImmutableEventDispatcher; /** * A basic form configuration. * * @author Bernhard Schussek */ class FormConfigBuilder implements FormConfigBuilderInterface { /** * Caches a globally unique {@link NativeRequestHandler} instance. * * @var NativeRequestHandler */ private static $nativeRequestProcessor; /** * The accepted request methods. * * @var array */ private static $allowedMethods = array( 'GET', 'PUT', 'POST', 'DELETE', 'PATCH' ); /** * @var Boolean */ protected $locked = false; /** * @var EventDispatcherInterface */ private $dispatcher; /** * @var string */ private $name; /** * @var PropertyPathInterface */ private $propertyPath; /** * @var Boolean */ private $mapped = true; /** * @var Boolean */ private $byReference = true; /** * @var Boolean */ private $inheritData = false; /** * @var Boolean */ private $compound = false; /** * @var ResolvedFormTypeInterface */ private $type; /** * @var array */ private $viewTransformers = array(); /** * @var array */ private $modelTransformers = array(); /** * @var DataMapperInterface */ private $dataMapper; /** * @var Boolean */ private $required = true; /** * @var Boolean */ private $disabled = false; /** * @var Boolean */ private $errorBubbling = false; /** * @var mixed */ private $emptyData; /** * @var array */ private $attributes = array(); /** * @var mixed */ private $data; /** * @var string */ private $dataClass; /** * @var Boolean */ private $dataLocked; /** * @var FormFactoryInterface */ private $formFactory; /** * @var string */ private $action; /** * @var string */ private $method = 'POST'; /** * @var RequestHandlerInterface */ private $requestHandler; /** * @var Boolean */ private $autoInitialize = false; /** * @var array */ private $options; /** * Creates an empty form configuration. * * @param string|integer $name The form name * @param string $dataClass The class of the form's data * @param EventDispatcherInterface $dispatcher The event dispatcher * @param array $options The form options * * @throws InvalidArgumentException If the data class is not a valid class or if * the name contains invalid characters. */ public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, array $options = array()) { self::validateName($name); if (null !== $dataClass && !class_exists($dataClass)) { throw new InvalidArgumentException(sprintf('The data class "%s" is not a valid class.', $dataClass)); } $this->name = (string) $name; $this->dataClass = $dataClass; $this->dispatcher = $dispatcher; $this->options = $options; } /** * {@inheritdoc} */ public function addEventListener($eventName, $listener, $priority = 0) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dispatcher->addListener($eventName, $listener, $priority); return $this; } /** * {@inheritdoc} */ public function addEventSubscriber(EventSubscriberInterface $subscriber) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dispatcher->addSubscriber($subscriber); return $this; } /** * {@inheritdoc} */ public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($forcePrepend) { array_unshift($this->viewTransformers, $viewTransformer); } else { $this->viewTransformers[] = $viewTransformer; } return $this; } /** * {@inheritdoc} */ public function resetViewTransformers() { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->viewTransformers = array(); return $this; } /** * {@inheritdoc} */ public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($forceAppend) { $this->modelTransformers[] = $modelTransformer; } else { array_unshift($this->modelTransformers, $modelTransformer); } return $this; } /** * {@inheritdoc} */ public function resetModelTransformers() { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->modelTransformers = array(); return $this; } /** * {@inheritdoc} */ public function getEventDispatcher() { if ($this->locked && !$this->dispatcher instanceof ImmutableEventDispatcher) { $this->dispatcher = new ImmutableEventDispatcher($this->dispatcher); } return $this->dispatcher; } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * {@inheritdoc} */ public function getPropertyPath() { return $this->propertyPath; } /** * {@inheritdoc} */ public function getMapped() { return $this->mapped; } /** * {@inheritdoc} */ public function getByReference() { return $this->byReference; } /** * {@inheritdoc} */ public function getInheritData() { return $this->inheritData; } /** * Alias of {@link getInheritData()}. * * @return FormConfigBuilder The configuration object. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link getInheritData()} instead. */ public function getVirtual() { // Uncomment this as soon as the deprecation note should be shown // trigger_error('getVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use getInheritData() instead.', E_USER_DEPRECATED); return $this->getInheritData(); } /** * {@inheritdoc} */ public function getCompound() { return $this->compound; } /** * {@inheritdoc} */ public function getType() { return $this->type; } /** * {@inheritdoc} */ public function getViewTransformers() { return $this->viewTransformers; } /** * {@inheritdoc} */ public function getModelTransformers() { return $this->modelTransformers; } /** * {@inheritdoc} */ public function getDataMapper() { return $this->dataMapper; } /** * {@inheritdoc} */ public function getRequired() { return $this->required; } /** * {@inheritdoc} */ public function getDisabled() { return $this->disabled; } /** * {@inheritdoc} */ public function getErrorBubbling() { return $this->errorBubbling; } /** * {@inheritdoc} */ public function getEmptyData() { return $this->emptyData; } /** * {@inheritdoc} */ public function getAttributes() { return $this->attributes; } /** * {@inheritdoc} */ public function hasAttribute($name) { return array_key_exists($name, $this->attributes); } /** * {@inheritdoc} */ public function getAttribute($name, $default = null) { return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** * {@inheritdoc} */ public function getData() { return $this->data; } /** * {@inheritdoc} */ public function getDataClass() { return $this->dataClass; } /** * {@inheritdoc} */ public function getDataLocked() { return $this->dataLocked; } /** * {@inheritdoc} */ public function getFormFactory() { return $this->formFactory; } /** * {@inheritdoc} */ public function getAction() { return $this->action; } /** * {@inheritdoc} */ public function getMethod() { return $this->method; } /** * {@inheritdoc} */ public function getRequestHandler() { if (null === $this->requestHandler) { if (null === self::$nativeRequestProcessor) { self::$nativeRequestProcessor = new NativeRequestHandler(); } $this->requestHandler = self::$nativeRequestProcessor; } return $this->requestHandler; } /** * {@inheritdoc} */ public function getAutoInitialize() { return $this->autoInitialize; } /** * {@inheritdoc} */ public function getOptions() { return $this->options; } /** * {@inheritdoc} */ public function hasOption($name) { return array_key_exists($name, $this->options); } /** * {@inheritdoc} */ public function getOption($name, $default = null) { return array_key_exists($name, $this->options) ? $this->options[$name] : $default; } /** * {@inheritdoc} */ public function setAttribute($name, $value) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->attributes[$name] = $value; return $this; } /** * {@inheritdoc} */ public function setAttributes(array $attributes) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->attributes = $attributes; return $this; } /** * {@inheritdoc} */ public function setDataMapper(DataMapperInterface $dataMapper = null) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dataMapper = $dataMapper; return $this; } /** * {@inheritdoc} */ public function setDisabled($disabled) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->disabled = (Boolean) $disabled; return $this; } /** * {@inheritdoc} */ public function setEmptyData($emptyData) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->emptyData = $emptyData; return $this; } /** * {@inheritdoc} */ public function setErrorBubbling($errorBubbling) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling; return $this; } /** * {@inheritdoc} */ public function setRequired($required) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->required = (Boolean) $required; return $this; } /** * {@inheritdoc} */ public function setPropertyPath($propertyPath) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (null !== $propertyPath && !$propertyPath instanceof PropertyPathInterface) { $propertyPath = new PropertyPath($propertyPath); } $this->propertyPath = $propertyPath; return $this; } /** * {@inheritdoc} */ public function setMapped($mapped) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->mapped = $mapped; return $this; } /** * {@inheritdoc} */ public function setByReference($byReference) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->byReference = $byReference; return $this; } /** * {@inheritdoc} */ public function setInheritData($inheritData) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->inheritData = $inheritData; return $this; } /** * Alias of {@link setInheritData()}. * * @param Boolean $inheritData Whether the form should inherit its parent's data. * * @return FormConfigBuilder The configuration object. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link setInheritData()} instead. */ public function setVirtual($inheritData) { // Uncomment this as soon as the deprecation note should be shown // trigger_error('setVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use setInheritData() instead.', E_USER_DEPRECATED); $this->setInheritData($inheritData); } /** * {@inheritdoc} */ public function setCompound($compound) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->compound = $compound; return $this; } /** * {@inheritdoc} */ public function setType(ResolvedFormTypeInterface $type) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->type = $type; return $this; } /** * {@inheritdoc} */ public function setData($data) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->data = $data; return $this; } /** * {@inheritdoc} */ public function setDataLocked($locked) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dataLocked = $locked; return $this; } /** * {@inheritdoc} */ public function setFormFactory(FormFactoryInterface $formFactory) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->formFactory = $formFactory; return $this; } /** * {@inheritdoc} */ public function setAction($action) { if ($this->locked) { throw new BadMethodCallException('The config builder cannot be modified anymore.'); } $this->action = $action; return $this; } /** * {@inheritdoc} */ public function setMethod($method) { if ($this->locked) { throw new BadMethodCallException('The config builder cannot be modified anymore.'); } $upperCaseMethod = strtoupper($method); if (!in_array($upperCaseMethod, self::$allowedMethods)) { throw new InvalidArgumentException(sprintf( 'The form method is "%s", but should be one of "%s".', $method, implode('", "', self::$allowedMethods) )); } $this->method = $upperCaseMethod; return $this; } /** * {@inheritdoc} */ public function setRequestHandler(RequestHandlerInterface $requestHandler) { if ($this->locked) { throw new BadMethodCallException('The config builder cannot be modified anymore.'); } $this->requestHandler = $requestHandler; return $this; } /** * {@inheritdoc} */ public function setAutoInitialize($initialize) { $this->autoInitialize = (Boolean) $initialize; return $this; } /** * {@inheritdoc} */ public function getFormConfig() { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } // This method should be idempotent, so clone the builder $config = clone $this; $config->locked = true; return $config; } /** * Validates whether the given variable is a valid form name. * * @param string|integer $name The tested form name. * * @throws UnexpectedTypeException If the name is not a string or an integer. * @throws InvalidArgumentException If the name contains invalid characters. */ public static function validateName($name) { if (null !== $name && !is_string($name) && !is_int($name)) { throw new UnexpectedTypeException($name, 'string, integer or null'); } if (!self::isValidName($name)) { throw new InvalidArgumentException(sprintf( 'The name "%s" contains illegal characters. Names should start with a letter, digit or underscore and only contain letters, digits, numbers, underscores ("_"), hyphens ("-") and colons (":").', $name )); } } /** * Returns whether the given variable contains a valid form name. * * A name is accepted if it * * * is empty * * starts with a letter, digit or underscore * * contains only letters, digits, numbers, underscores ("_"), * hyphens ("-") and colons (":") * * @param string $name The tested form name. * * @return Boolean Whether the name is valid. */ public static function isValidName($name) { return '' === $name || null === $name || preg_match('/^[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', $name); } } PK]s Form/FormInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A form group bundling multiple forms in a hierarchical structure. * * @author Bernhard Schussek */ interface FormInterface extends \ArrayAccess, \Traversable, \Countable { /** * Sets the parent form. * * @param FormInterface|null $parent The parent form or null if it's the root. * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException When trying to set a parent for a form with * an empty name. */ public function setParent(FormInterface $parent = null); /** * Returns the parent form. * * @return FormInterface|null The parent form or null if there is none. */ public function getParent(); /** * Adds or replaces a child to the form. * * @param FormInterface|string|integer $child The FormInterface instance or the name of the child. * @param string|null $type The child's type, if a name was passed. * @param array $options The child's options, if a name was passed. * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException When trying to add a child to a non-compound form. * @throws Exception\UnexpectedTypeException If $child or $type has an unexpected type. */ public function add($child, $type = null, array $options = array()); /** * Returns the child with the given name. * * @param string $name The name of the child * * @return FormInterface The child form * * @throws \OutOfBoundsException If the named child does not exist. */ public function get($name); /** * Returns whether a child with the given name exists. * * @param string $name The name of the child * * @return Boolean */ public function has($name); /** * Removes a child from the form. * * @param string $name The name of the child to remove * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ public function remove($name); /** * Returns all children in this group. * * @return FormInterface[] An array of FormInterface instances */ public function all(); /** * Returns all errors. * * @return FormError[] An array of FormError instances that occurred during validation */ public function getErrors(); /** * Updates the form with default data. * * @param mixed $modelData The data formatted as expected for the underlying object * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException If listeners try to call setData in a cycle. Or if * the view data does not match the expected type * according to {@link FormConfigInterface::getDataClass}. */ public function setData($modelData); /** * Returns the data in the format needed for the underlying object. * * @return mixed */ public function getData(); /** * Returns the normalized data of the field. * * @return mixed When the field is not submitted, the default data is returned. * When the field is submitted, the normalized submitted data is * returned if the field is valid, null otherwise. */ public function getNormData(); /** * Returns the data transformed by the value transformer. * * @return mixed */ public function getViewData(); /** * Returns the extra data. * * @return array The submitted data which do not belong to a child */ public function getExtraData(); /** * Returns the form's configuration. * * @return FormConfigInterface The configuration. */ public function getConfig(); /** * Returns whether the form is submitted. * * @return Boolean true if the form is submitted, false otherwise */ public function isSubmitted(); /** * Returns the name by which the form is identified in forms. * * @return string The name of the form. */ public function getName(); /** * Returns the property path that the form is mapped to. * * @return \Symfony\Component\PropertyAccess\PropertyPathInterface The property path. */ public function getPropertyPath(); /** * Adds an error to this form. * * @param FormError $error * * @return FormInterface The form instance */ public function addError(FormError $error); /** * Returns whether the form and all children are valid. * * If the form is not submitted, this method always returns false. * * @return Boolean */ public function isValid(); /** * Returns whether the form is required to be filled out. * * If the form has a parent and the parent is not required, this method * will always return false. Otherwise the value set with setRequired() * is returned. * * @return Boolean */ public function isRequired(); /** * Returns whether this form is disabled. * * The content of a disabled form is displayed, but not allowed to be * modified. The validation of modified disabled forms should fail. * * Forms whose parents are disabled are considered disabled regardless of * their own state. * * @return Boolean */ public function isDisabled(); /** * Returns whether the form is empty. * * @return Boolean */ public function isEmpty(); /** * Returns whether the data in the different formats is synchronized. * * @return Boolean */ public function isSynchronized(); /** * Initializes the form tree. * * Should be called on the root form after constructing the tree. * * @return FormInterface The form instance. */ public function initialize(); /** * Inspects the given request and calls {@link submit()} if the form was * submitted. * * Internally, the request is forwarded to the configured * {@link RequestHandlerInterface} instance, which determines whether to * submit the form or not. * * @param mixed $request The request to handle. * * @return FormInterface The form instance. */ public function handleRequest($request = null); /** * Submits data to the form, transforms and validates it. * * @param null|string|array $submittedData The submitted data. * @param Boolean $clearMissing Whether to set fields to NULL * when they are missing in the * submitted data. * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ public function submit($submittedData, $clearMissing = true); /** * Returns the root of the form tree. * * @return FormInterface The root of the tree */ public function getRoot(); /** * Returns whether the field is the root of the form tree. * * @return Boolean */ public function isRoot(); /** * Creates a view. * * @param FormView $parent The parent view * * @return FormView The view */ public function createView(FormView $parent = null); } PK]dForm/FormRegistry.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\ExceptionInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * The central registry of the Form component. * * @author Bernhard Schussek */ class FormRegistry implements FormRegistryInterface { /** * Extensions * * @var FormExtensionInterface[] An array of FormExtensionInterface */ private $extensions = array(); /** * @var array */ private $types = array(); /** * @var FormTypeGuesserInterface|false|null */ private $guesser = false; /** * @var ResolvedFormTypeFactoryInterface */ private $resolvedTypeFactory; /** * Constructor. * * @param FormExtensionInterface[] $extensions An array of FormExtensionInterface * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory The factory for resolved form types. * * @throws UnexpectedTypeException if any extension does not implement FormExtensionInterface */ public function __construct(array $extensions, ResolvedFormTypeFactoryInterface $resolvedTypeFactory) { foreach ($extensions as $extension) { if (!$extension instanceof FormExtensionInterface) { throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormExtensionInterface'); } } $this->extensions = $extensions; $this->resolvedTypeFactory = $resolvedTypeFactory; } /** * {@inheritdoc} */ public function getType($name) { if (!is_string($name)) { throw new UnexpectedTypeException($name, 'string'); } if (!isset($this->types[$name])) { /** @var FormTypeInterface $type */ $type = null; foreach ($this->extensions as $extension) { /* @var FormExtensionInterface $extension */ if ($extension->hasType($name)) { $type = $extension->getType($name); break; } } if (!$type) { throw new InvalidArgumentException(sprintf('Could not load type "%s"', $name)); } $this->resolveAndAddType($type); } return $this->types[$name]; } /** * Wraps a type into a ResolvedFormTypeInterface implementation and connects * it with its parent type. * * @param FormTypeInterface $type The type to resolve. * * @return ResolvedFormTypeInterface The resolved type. */ private function resolveAndAddType(FormTypeInterface $type) { $parentType = $type->getParent(); if ($parentType instanceof FormTypeInterface) { $this->resolveAndAddType($parentType); $parentType = $parentType->getName(); } $typeExtensions = array(); foreach ($this->extensions as $extension) { /* @var FormExtensionInterface $extension */ $typeExtensions = array_merge( $typeExtensions, $extension->getTypeExtensions($type->getName()) ); } $this->types[$type->getName()] = $this->resolvedTypeFactory->createResolvedType( $type, $typeExtensions, $parentType ? $this->getType($parentType) : null ); } /** * {@inheritdoc} */ public function hasType($name) { if (isset($this->types[$name])) { return true; } try { $this->getType($name); } catch (ExceptionInterface $e) { return false; } return true; } /** * {@inheritdoc} */ public function getTypeGuesser() { if (false === $this->guesser) { $guessers = array(); foreach ($this->extensions as $extension) { /* @var FormExtensionInterface $extension */ $guesser = $extension->getTypeGuesser(); if ($guesser) { $guessers[] = $guesser; } } $this->guesser = !empty($guessers) ? new FormTypeGuesserChain($guessers) : null; } return $this->guesser; } /** * {@inheritdoc} */ public function getExtensions() { return $this->extensions; } } PK]a(0kkForm/Test/FormInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; interface FormInterface extends \Iterator, \Symfony\Component\Form\FormInterface { } PK]myy"Form/Test/FormBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; interface FormBuilderInterface extends \Iterator, \Symfony\Component\Form\FormBuilderInterface { } PK]sŪForm/Test/TypeTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; use Symfony\Component\Form\FormBuilder; use Symfony\Component\EventDispatcher\EventDispatcher; abstract class TypeTestCase extends FormIntegrationTestCase { /** * @var FormBuilder */ protected $builder; /** * @var EventDispatcher */ protected $dispatcher; protected function setUp() { parent::setUp(); $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory); } public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) { self::assertEquals($expected->format('c'), $actual->format('c')); } } PK]B4I++%Form/Test/FormIntegrationTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; use Symfony\Component\Form\Forms; /** * @author Bernhard Schussek */ abstract class FormIntegrationTestCase extends \PHPUnit_Framework_TestCase { /** * @var \Symfony\Component\Form\FormFactoryInterface */ protected $factory; protected function setUp() { $this->factory = Forms::createFormFactoryBuilder() ->addExtensions($this->getExtensions()) ->getFormFactory(); } protected function getExtensions() { return array(); } } PK],7//%Form/Test/DeprecationErrorHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; use Symfony\Component\Form\FormEvent; class DeprecationErrorHandler { public static function handle($errorNumber, $message, $file, $line, $context) { if ($errorNumber & E_USER_DEPRECATED) { return true; } return \PHPUnit_Util_ErrorHandler::handleError($errorNumber, $message, $file, $line); } public static function handleBC($errorNumber, $message, $file, $line, $context) { if ($errorNumber & E_USER_DEPRECATED) { return true; } return false; } public static function preBind($listener, FormEvent $event) { set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $listener->preBind($event); restore_error_handler(); } } PK]+qDAA%Form/Test/FormPerformanceTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; /** * Base class for performance tests. * * Copied from Doctrine 2's OrmPerformanceTestCase. * * @author robo * @author Bernhard Schussek */ abstract class FormPerformanceTestCase extends FormIntegrationTestCase { /** * @var integer */ protected $maxRunningTime = 0; /** */ protected function runTest() { $s = microtime(true); parent::runTest(); $time = microtime(true) - $s; if ($this->maxRunningTime != 0 && $time > $this->maxRunningTime) { $this->fail( sprintf( 'expected running time: <= %s but was: %s', $this->maxRunningTime, $time ) ); } } /** * @param integer $maxRunningTime * @throws \InvalidArgumentException */ public function setMaxRunningTime($maxRunningTime) { if (is_integer($maxRunningTime) && $maxRunningTime >= 0) { $this->maxRunningTime = $maxRunningTime; } else { throw new \InvalidArgumentException(); } } /** * @return integer * @since Method available since Release 2.3.0 */ public function getMaxRunningTime() { return $this->maxRunningTime; } } PK] Form/NativeRequestHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * A request handler using PHP's super globals $_GET, $_POST and $_SERVER. * * @author Bernhard Schussek */ class NativeRequestHandler implements RequestHandlerInterface { /** * The allowed keys of the $_FILES array. * * @var array */ private static $fileKeys = array( 'error', 'name', 'size', 'tmp_name', 'type', ); /** * {@inheritdoc} */ public function handleRequest(FormInterface $form, $request = null) { if (null !== $request) { throw new UnexpectedTypeException($request, 'null'); } $name = $form->getName(); $method = $form->getConfig()->getMethod(); if ($method !== self::getRequestMethod()) { return; } if ('GET' === $method) { if ('' === $name) { $data = $_GET; } else { // Don't submit GET requests if the form's name does not exist // in the request if (!isset($_GET[$name])) { return; } $data = $_GET[$name]; } } else { $fixedFiles = array(); foreach ($_FILES as $name => $file) { $fixedFiles[$name] = self::stripEmptyFiles(self::fixPhpFilesArray($file)); } if ('' === $name) { $params = $_POST; $files = $fixedFiles; } elseif (array_key_exists($name, $_POST) || array_key_exists($name, $fixedFiles)) { $default = $form->getConfig()->getCompound() ? array() : null; $params = array_key_exists($name, $_POST) ? $_POST[$name] : $default; $files = array_key_exists($name, $fixedFiles) ? $fixedFiles[$name] : $default; } else { // Don't submit the form if it is not present in the request return; } if (is_array($params) && is_array($files)) { $data = array_replace_recursive($params, $files); } else { $data = $params ?: $files; } } // Don't auto-submit the form unless at least one field is present. if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) { return; } $form->submit($data, 'PATCH' !== $method); } /** * Returns the method used to submit the request to the server. * * @return string The request method. */ private static function getRequestMethod() { $method = isset($_SERVER['REQUEST_METHOD']) ? strtoupper($_SERVER['REQUEST_METHOD']) : 'GET'; if ('POST' === $method && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { $method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); } return $method; } /** * Fixes a malformed PHP $_FILES array. * * PHP has a bug that the format of the $_FILES array differs, depending on * whether the uploaded file fields had normal field names or array-like * field names ("normal" vs. "parent[child]"). * * This method fixes the array to look like the "normal" $_FILES array. * * It's safe to pass an already converted array, in which case this method * just returns the original array unmodified. * * This method is identical to {@link Symfony\Component\HttpFoundation\FileBag::fixPhpFilesArray} * and should be kept as such in order to port fixes quickly and easily. * * @param array $data * * @return array */ private static function fixPhpFilesArray($data) { if (!is_array($data)) { return $data; } $keys = array_keys($data); sort($keys); if (self::$fileKeys !== $keys || !isset($data['name']) || !is_array($data['name'])) { return $data; } $files = $data; foreach (self::$fileKeys as $k) { unset($files[$k]); } foreach (array_keys($data['name']) as $key) { $files[$key] = self::fixPhpFilesArray(array( 'error' => $data['error'][$key], 'name' => $data['name'][$key], 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key] )); } return $files; } /** * Sets empty uploaded files to NULL in the given uploaded files array. * * @param mixed $data The file upload data. * * @return array|null Returns the stripped upload data. */ private static function stripEmptyFiles($data) { if (!is_array($data)) { return $data; } $keys = array_keys($data); sort($keys); if (self::$fileKeys === $keys) { if (UPLOAD_ERR_NO_FILE === $data['error']) { return null; } return $data; } foreach ($data as $key => $value) { $data[$key] = self::stripEmptyFiles($value); } return $data; } } PK] f2Form/Extension/Csrf/Type/FormTypeCsrfExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfTokenManagerAdapter; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** * @author Bernhard Schussek */ class FormTypeCsrfExtension extends AbstractTypeExtension { /** * @var CsrfTokenManagerInterface */ private $defaultTokenManager; /** * @var Boolean */ private $defaultEnabled; /** * @var string */ private $defaultFieldName; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; public function __construct($defaultTokenManager, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null) { if ($defaultTokenManager instanceof CsrfProviderInterface) { $defaultTokenManager = new CsrfProviderAdapter($defaultTokenManager); } elseif (!$defaultTokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($defaultTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $this->defaultTokenManager = $defaultTokenManager; $this->defaultEnabled = $defaultEnabled; $this->defaultFieldName = $defaultFieldName; $this->translator = $translator; $this->translationDomain = $translationDomain; } /** * Adds a CSRF field to the form when the CSRF protection is enabled. * * @param FormBuilderInterface $builder The form builder * @param array $options The options */ public function buildForm(FormBuilderInterface $builder, array $options) { if (!$options['csrf_protection']) { return; } $builder ->addEventSubscriber(new CsrfValidationListener( $options['csrf_field_name'], $options['csrf_token_manager'], $options['csrf_token_id'] ?: ($builder->getName() ?: get_class($builder->getType()->getInnerType())), $options['csrf_message'], $this->translator, $this->translationDomain )) ; } /** * Adds a CSRF field to the root form view. * * @param FormView $view The form view * @param FormInterface $form The form * @param array $options The options */ public function finishView(FormView $view, FormInterface $form, array $options) { if ($options['csrf_protection'] && !$view->parent && $options['compound']) { $factory = $form->getConfig()->getFormFactory(); $tokenId = $options['csrf_token_id'] ?: ($form->getName() ?: get_class($form->getConfig()->getType()->getInnerType())); $data = (string) $options['csrf_token_manager']->getToken($tokenId); $csrfForm = $factory->createNamed($options['csrf_field_name'], 'hidden', $data, array( 'mapped' => false, )); $view->children[$options['csrf_field_name']] = $csrfForm->createView($view); } } /** * {@inheritDoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { // BC clause for the "intention" option $csrfTokenId = function (Options $options) { return $options['intention']; }; // BC clause for the "csrf_provider" option $csrfTokenManager = function (Options $options) { return $options['csrf_provider'] instanceof CsrfTokenManagerAdapter ? $options['csrf_provider']->getTokenManager() : new CsrfProviderAdapter($options['csrf_provider']); }; $resolver->setDefaults(array( 'csrf_protection' => $this->defaultEnabled, 'csrf_field_name' => $this->defaultFieldName, 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', 'csrf_token_manager' => $csrfTokenManager, 'csrf_token_id' => $csrfTokenId, 'csrf_provider' => new CsrfTokenManagerAdapter($this->defaultTokenManager), 'intention' => null, )); } /** * {@inheritDoc} */ public function getExtendedType() { return 'form'; } } PK]"q%Form/Extension/Csrf/CsrfExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** * This extension protects forms by using a CSRF token. * * @author Bernhard Schussek */ class CsrfExtension extends AbstractExtension { /** * @var CsrfTokenManagerInterface */ private $tokenManager; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * Constructor. * * @param CsrfTokenManagerInterface $tokenManager The CSRF token manager * @param TranslatorInterface $translator The translator for translating error messages * @param null|string $translationDomain The translation domain for translating */ public function __construct($tokenManager, TranslatorInterface $translator = null, $translationDomain = null) { if ($tokenManager instanceof CsrfProviderInterface) { $tokenManager = new CsrfProviderAdapter($tokenManager); } elseif (!$tokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($tokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $this->tokenManager = $tokenManager; $this->translator = $translator; $this->translationDomain = $translationDomain; } /** * {@inheritDoc} */ protected function loadTypeExtensions() { return array( new Type\FormTypeCsrfExtension($this->tokenManager, true, '_token', $this->translator, $this->translationDomain), ); } } PK]R'WTT<Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * Adapter for using the new token generator with the old interface. * * @since 2.4 * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. */ class CsrfTokenManagerAdapter implements CsrfProviderInterface { /** * @var CsrfTokenManagerInterface */ private $tokenManager; public function __construct(CsrfTokenManagerInterface $tokenManager) { $this->tokenManager = $tokenManager; } public function getTokenManager() { return $this->tokenManager; } /** * {@inheritdoc} */ public function generateCsrfToken($intention) { return $this->tokenManager->getToken($intention)->getValue(); } /** * {@inheritdoc} */ public function isCsrfTokenValid($intention, $token) { return $this->tokenManager->isTokenValid(new CsrfToken($intention, $token)); } } PK]8Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * Adapter for using old CSRF providers where the new {@link CsrfTokenManagerInterface} * is expected. * * @since 2.4 * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. */ class CsrfProviderAdapter implements CsrfTokenManagerInterface { /** * @var CsrfProviderInterface */ private $csrfProvider; public function __construct(CsrfProviderInterface $csrfProvider) { $this->csrfProvider = $csrfProvider; } public function getCsrfProvider() { return $this->csrfProvider; } /** * {@inheritdoc} */ public function getToken($tokenId) { return new CsrfToken($tokenId, $this->csrfProvider->generateCsrfToken($tokenId)); } /** * {@inheritdoc} */ public function refreshToken($tokenId) { throw new BadMethodCallException('Not supported'); } /** * {@inheritdoc} */ public function removeToken($tokenId) { throw new BadMethodCallException('Not supported'); } /** * {@inheritdoc} */ public function isTokenValid(CsrfToken $token) { return $this->csrfProvider->isCsrfTokenValid($token->getId(), $token->getValue()); } } PK]%G:Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; /** * Marks classes able to provide CSRF protection * * You can generate a CSRF token by using the method generateCsrfToken(). To * this method you should pass a value that is unique to the page that should * be secured against CSRF attacks. This value doesn't necessarily have to be * secret. Implementations of this interface are responsible for adding more * secret information. * * If you want to secure a form submission against CSRF attacks, you could * supply an "intention" string. This way you make sure that the form can only * be submitted to pages that are designed to handle the form, that is, that use * the same intention string to validate the CSRF token with isCsrfTokenValid(). * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use * {@link \Symfony\Component\Security\Csrf\CsrfTokenManagerInterface} * instead. */ interface CsrfProviderInterface { /** * Generates a CSRF token for a page of your application. * * @param string $intention Some value that identifies the action intention * (i.e. "authenticate"). Doesn't have to be a secret value. * * @return string The generated token */ public function generateCsrfToken($intention); /** * Validates a CSRF token. * * @param string $intention The intention used when generating the CSRF token * @param string $token The token supplied by the browser * * @return Boolean Whether the token supplied by the browser is correct */ public function isCsrfTokenValid($intention, $token); } PK][^8Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; use Symfony\Component\HttpFoundation\Session\Session; /** * This provider uses a Symfony2 Session object to retrieve the user's * session ID. * * @see DefaultCsrfProvider * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use * {@link \Symfony\Component\Security\Csrf\CsrfTokenManager} in * combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage} * instead. */ class SessionCsrfProvider extends DefaultCsrfProvider { /** * The user session from which the session ID is returned * @var Session */ protected $session; /** * Initializes the provider with a Session object and a secret value. * * A recommended value for the secret is a generated value with at least * 32 characters and mixed letters, digits and special characters. * * @param Session $session The user session * @param string $secret A secret value included in the CSRF token */ public function __construct(Session $session, $secret) { parent::__construct($secret); $this->session = $session; } /** * {@inheritdoc} */ protected function getSessionId() { $this->session->start(); return $this->session->getId(); } } PK]C8Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; /** * Default implementation of CsrfProviderInterface. * * This provider uses the session ID returned by session_id() as well as a * user-defined secret value to secure the CSRF token. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use * {@link \Symfony\Component\Security\Csrf\CsrfTokenManager} in * combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage} * instead. */ class DefaultCsrfProvider implements CsrfProviderInterface { /** * A secret value used for generating the CSRF token * @var string */ protected $secret; /** * Initializes the provider with a secret value * * A recommended value for the secret is a generated value with at least * 32 characters and mixed letters, digits and special characters. * * @param string $secret A secret value included in the CSRF token */ public function __construct($secret) { $this->secret = $secret; } /** * {@inheritDoc} */ public function generateCsrfToken($intention) { return sha1($this->secret.$intention.$this->getSessionId()); } /** * {@inheritDoc} */ public function isCsrfTokenValid($intention, $token) { return $token === $this->generateCsrfToken($intention); } /** * Returns the ID of the user session. * * Automatically starts the session if necessary. * * @return string The session ID */ protected function getSessionId() { if (version_compare(PHP_VERSION, '5.4', '>=')) { if (PHP_SESSION_NONE === session_status()) { session_start(); } } elseif (!session_id()) { session_start(); } return session_id(); } } PK]?oo<Form/Extension/Csrf/EventListener/CsrfValidationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormEvent; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** * @author Bernhard Schussek */ class CsrfValidationListener implements EventSubscriberInterface { /** * The name of the CSRF field * @var string */ private $fieldName; /** * The generator for CSRF tokens * @var CsrfTokenManagerInterface */ private $tokenManager; /** * A text mentioning the tokenId of the CSRF token * * Validation of the token will only succeed if it was generated in the * same session and with the same tokenId. * * @var string */ private $tokenId; /** * The message displayed in case of an error. * @var string */ private $errorMessage; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; public static function getSubscribedEvents() { return array( FormEvents::PRE_SUBMIT => 'preSubmit', ); } public function __construct($fieldName, $tokenManager, $tokenId, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null) { if ($tokenManager instanceof CsrfProviderInterface) { $tokenManager = new CsrfProviderAdapter($tokenManager); } elseif (!$tokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($tokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $this->fieldName = $fieldName; $this->tokenManager = $tokenManager; $this->tokenId = $tokenId; $this->errorMessage = $errorMessage; $this->translator = $translator; $this->translationDomain = $translationDomain; } public function preSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if ($form->isRoot() && $form->getConfig()->getOption('compound')) { if (!isset($data[$this->fieldName]) || !$this->tokenManager->isTokenValid(new CsrfToken($this->tokenId, $data[$this->fieldName]))) { $errorMessage = $this->errorMessage; if (null !== $this->translator) { $errorMessage = $this->translator->trans($errorMessage, array(), $this->translationDomain); } $form->addError(new FormError($errorMessage)); } if (is_array($data)) { unset($data[$this->fieldName]); } } $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } } PK]զY6Form/Extension/Templating/TemplatingRendererEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Templating; use Symfony\Component\Form\AbstractRendererEngine; use Symfony\Component\Form\FormView; use Symfony\Component\Templating\EngineInterface; /** * @author Bernhard Schussek */ class TemplatingRendererEngine extends AbstractRendererEngine { /** * @var EngineInterface */ private $engine; public function __construct(EngineInterface $engine, array $defaultThemes = array()) { parent::__construct($defaultThemes); $this->engine = $engine; } /** * {@inheritdoc} */ public function renderBlock(FormView $view, $resource, $blockName, array $variables = array()) { return trim($this->engine->render($resource, $variables)); } /** * Loads the cache with the resource for a given block name. * * This implementation tries to load as few blocks as possible, since each block * is represented by a template on the file system. * * @see getResourceForBlock() * * @param string $cacheKey The cache key of the form view. * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * * @return Boolean True if the resource could be loaded, false otherwise. */ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName) { // Recursively try to find the block in the themes assigned to $view, // then of its parent form, then of the parent form of the parent and so on. // When the root form is reached in this recursion, also the default // themes are taken into account. // Check each theme whether it contains the searched block if (isset($this->themes[$cacheKey])) { for ($i = count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) { if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->themes[$cacheKey][$i])) { return true; } } } // Check the default themes once we reach the root form without success if (!$view->parent) { for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) { if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->defaultThemes[$i])) { return true; } } } // If we did not find anything in the themes of the current view, proceed // with the themes of the parent view if ($view->parent) { $parentCacheKey = $view->parent->vars[self::CACHE_KEY_VAR]; if (!isset($this->resources[$parentCacheKey][$blockName])) { $this->loadResourceForBlockName($parentCacheKey, $view->parent, $blockName); } // If a template exists in the parent themes, cache that template // for the current theme as well to speed up further accesses if ($this->resources[$parentCacheKey][$blockName]) { $this->resources[$cacheKey][$blockName] = $this->resources[$parentCacheKey][$blockName]; return true; } } // Cache that we didn't find anything to speed up further accesses $this->resources[$cacheKey][$blockName] = false; return false; } /** * Tries to load the resource for a block from a theme. * * @param string $cacheKey The cache key for storing the resource. * @param string $blockName The name of the block to load a resource for. * @param mixed $theme The theme to load the block from. * * @return Boolean True if the resource could be loaded, false otherwise. */ protected function loadResourceFromTheme($cacheKey, $blockName, $theme) { if ($this->engine->exists($templateName = $theme.':'.$blockName.'.html.php')) { $this->resources[$cacheKey][$blockName] = $templateName; return true; } return false; } } PK],QQ1Form/Extension/Templating/TemplatingExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Templating; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\FormRenderer; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Templating\PhpEngine; use Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper; /** * Integrates the Templating component with the Form library. * * @author Bernhard Schussek */ class TemplatingExtension extends AbstractExtension { public function __construct(PhpEngine $engine, $csrfTokenManager = null, array $defaultThemes = array()) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $engine->addHelpers(array( new FormHelper(new FormRenderer(new TemplatingRendererEngine($engine, $defaultThemes), $csrfTokenManager)) )); } } PK]uUSW W CForm/Extension/DependencyInjection/DependencyInjectionExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DependencyInjection; use Symfony\Component\Form\FormExtensionInterface; use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\ContainerInterface; class DependencyInjectionExtension implements FormExtensionInterface { private $container; private $typeServiceIds; private $typeExtensionServiceIds; private $guesserServiceIds; private $guesser; private $guesserLoaded = false; public function __construct(ContainerInterface $container, array $typeServiceIds, array $typeExtensionServiceIds, array $guesserServiceIds) { $this->container = $container; $this->typeServiceIds = $typeServiceIds; $this->typeExtensionServiceIds = $typeExtensionServiceIds; $this->guesserServiceIds = $guesserServiceIds; } public function getType($name) { if (!isset($this->typeServiceIds[$name])) { throw new InvalidArgumentException(sprintf('The field type "%s" is not registered with the service container.', $name)); } $type = $this->container->get($this->typeServiceIds[$name]); if ($type->getName() !== $name) { throw new InvalidArgumentException( sprintf('The type name specified for the service "%s" does not match the actual name. Expected "%s", given "%s"', $this->typeServiceIds[$name], $name, $type->getName() )); } return $type; } public function hasType($name) { return isset($this->typeServiceIds[$name]); } public function getTypeExtensions($name) { $extensions = array(); if (isset($this->typeExtensionServiceIds[$name])) { foreach ($this->typeExtensionServiceIds[$name] as $serviceId) { $extensions[] = $this->container->get($serviceId); } } return $extensions; } public function hasTypeExtensions($name) { return isset($this->typeExtensionServiceIds[$name]); } public function getTypeGuesser() { if (!$this->guesserLoaded) { $this->guesserLoaded = true; $guessers = array(); foreach ($this->guesserServiceIds as $serviceId) { $guessers[] = $this->container->get($serviceId); } if (count($guessers) > 0) { $this->guesser = new FormTypeGuesserChain($guessers); } } return $this->guesser; } } PK]#117Form/Extension/DataCollector/DataCollectorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\AbstractExtension; /** * Extension for collecting data of the forms on a page. * * @since 2.4 * @author Robert Schönthal * @author Bernhard Schussek */ class DataCollectorExtension extends AbstractExtension { /** * @var EventSubscriberInterface */ private $dataCollector; public function __construct(FormDataCollectorInterface $dataCollector) { $this->dataCollector = $dataCollector; } /** * {@inheritDoc} */ protected function loadTypeExtensions() { return array( new Type\DataCollectorTypeExtension($this->dataCollector) ); } } PK]1 uu@Form/Extension/DataCollector/Type/DataCollectorTypeExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormBuilderInterface; /** * Type extension for collecting data of a form with this type. * * @since 2.4 * @author Robert Schönthal * @author Bernhard Schussek */ class DataCollectorTypeExtension extends AbstractTypeExtension { /** * @var \Symfony\Component\EventDispatcher\EventSubscriberInterface */ private $listener; public function __construct(FormDataCollectorInterface $dataCollector) { $this->listener = new DataCollectorListener($dataCollector); } /** * {@inheritDoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber($this->listener); } /** * {@inheritDoc} */ public function getExtendedType() { return 'form'; } } PK];Form/Extension/DataCollector/FormDataExtractorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; /** * Extracts arrays of information out of forms. * * @since 2.4 * @author Bernhard Schussek */ interface FormDataExtractorInterface { /** * Extracts the configuration data of a form. * * @param FormInterface $form The form * * @return array Information about the form's configuration */ public function extractConfiguration(FormInterface $form); /** * Extracts the default data of a form. * * @param FormInterface $form The form * * @return array Information about the form's default data */ public function extractDefaultData(FormInterface $form); /** * Extracts the submitted data of a form. * * @param FormInterface $form The form * * @return array Information about the form's submitted data */ public function extractSubmittedData(FormInterface $form); /** * Extracts the view variables of a form. * * @param FormView $view The form view * * @return array Information about the view's variables */ public function extractViewVariables(FormView $view); } PK]| ]EForm/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\Proxy; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\ResolvedFormTypeInterface; /** * Proxy that invokes a data collector when creating a form and its view. * * @since 2.4 * @author Bernhard Schussek */ class ResolvedTypeDataCollectorProxy implements ResolvedFormTypeInterface { /** * @var ResolvedFormTypeInterface */ private $proxiedType; /** * @var FormDataCollectorInterface */ private $dataCollector; public function __construct(ResolvedFormTypeInterface $proxiedType, FormDataCollectorInterface $dataCollector) { $this->proxiedType = $proxiedType; $this->dataCollector = $dataCollector; } /** * {@inheritdoc} */ public function getName() { return $this->proxiedType->getName(); } /** * {@inheritdoc} */ public function getParent() { return $this->proxiedType->getParent(); } /** * {@inheritdoc} */ public function getInnerType() { return $this->proxiedType->getInnerType(); } /** * {@inheritdoc} */ public function getTypeExtensions() { return $this->proxiedType->getTypeExtensions(); } /** * {@inheritdoc} */ public function createBuilder(FormFactoryInterface $factory, $name, array $options = array()) { $builder = $this->proxiedType->createBuilder($factory, $name, $options); $builder->setAttribute('data_collector/passed_options', $options); $builder->setType($this); return $builder; } /** * {@inheritdoc} */ public function createView(FormInterface $form, FormView $parent = null) { return $this->proxiedType->createView($form, $parent); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $this->proxiedType->buildForm($builder, $options); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $this->proxiedType->buildView($view, $form, $options); } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $this->proxiedType->finishView($view, $form, $options); // Remember which view belongs to which form instance, so that we can // get the collected data for a view when its form instance is not // available (e.g. CSRF token) $this->dataCollector->associateFormWithView($form, $view); // Since the CSRF token is only present in the FormView tree, we also // need to check the FormView tree instead of calling isRoot() on the // FormInterface tree if (null === $view->parent) { $this->dataCollector->collectViewVariables($view); // Re-assemble data, in case FormView instances were added, for // which no FormInterface instances were present (e.g. CSRF token). // Since finishView() is called after finishing the views of all // children, we can safely assume that information has been // collected about the complete form tree. $this->dataCollector->buildFinalFormTree($form, $view); } } /** * {@inheritdoc} */ public function getOptionsResolver() { return $this->proxiedType->getOptionsResolver(); } } PK]((LForm/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\Proxy; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\Form\ResolvedFormTypeFactoryInterface; use Symfony\Component\Form\ResolvedFormTypeInterface; /** * Proxy that wraps resolved types into {@link ResolvedTypeDataCollectorProxy} * instances. * * @since 2.4 * @author Bernhard Schussek */ class ResolvedTypeFactoryDataCollectorProxy implements ResolvedFormTypeFactoryInterface { /** * @var ResolvedFormTypeFactoryInterface */ private $proxiedFactory; /** * @var FormDataCollectorInterface */ private $dataCollector; public function __construct(ResolvedFormTypeFactoryInterface $proxiedFactory, FormDataCollectorInterface $dataCollector) { $this->proxiedFactory = $proxiedFactory; $this->dataCollector = $dataCollector; } /** * {@inheritdoc} */ public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null) { return new ResolvedTypeDataCollectorProxy( $this->proxiedFactory->createResolvedType($type, $typeExtensions, $parent), $this->dataCollector ); } } PK]I2  DForm/Extension/DataCollector/EventListener/DataCollectorListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; /** * Listener that invokes a data collector for the {@link FormEvents::POST_SET_DATA} * and {@link FormEvents::POST_SUBMIT} events. * * @since 2.4 * @author Bernhard Schussek */ class DataCollectorListener implements EventSubscriberInterface { /** * @var FormDataCollectorInterface */ private $dataCollector; public function __construct(FormDataCollectorInterface $dataCollector) { $this->dataCollector = $dataCollector; } /** * {@inheritDoc} */ public static function getSubscribedEvents() { return array( // High priority in order to be called as soon as possible FormEvents::POST_SET_DATA => array('postSetData', 255), // Low priority in order to be called as late as possible FormEvents::POST_SUBMIT => array('postSubmit', -255), ); } /** * Listener for the {@link FormEvents::POST_SET_DATA} event. * * @param FormEvent $event The event object */ public function postSetData(FormEvent $event) { if ($event->getForm()->isRoot()) { // Collect basic information about each form $this->dataCollector->collectConfiguration($event->getForm()); // Collect the default data $this->dataCollector->collectDefaultData($event->getForm()); } } /** * Listener for the {@link FormEvents::POST_SUBMIT} event. * * @param FormEvent $event The event object */ public function postSubmit(FormEvent $event) { if ($event->getForm()->isRoot()) { // Collect the submitted data of each form $this->dataCollector->collectSubmittedData($event->getForm()); // Assemble a form tree // This is done again in collectViewVariables(), but that method // is not guaranteed to be called (i.e. when no view is created) $this->dataCollector->buildPreliminaryFormTree($event->getForm()); } } } PK]6s2Form/Extension/DataCollector/FormDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollector; /** * Data collector for {@link \Symfony\Component\Form\FormInterface} instances. * * @since 2.4 * @author Robert Schönthal * @author Bernhard Schussek */ class FormDataCollector extends DataCollector implements FormDataCollectorInterface { /** * @var FormDataExtractor */ private $dataExtractor; /** * Stores the collected data per {@link FormInterface} instance. * * Uses the hashes of the forms as keys. This is preferable over using * {@link \SplObjectStorage}, because in this way no references are kept * to the {@link FormInterface} instances. * * @var array */ private $dataByForm; /** * Stores the collected data per {@link FormView} instance. * * Uses the hashes of the views as keys. This is preferable over using * {@link \SplObjectStorage}, because in this way no references are kept * to the {@link FormView} instances. * * @var array */ private $dataByView; /** * Connects {@link FormView} with {@link FormInterface} instances. * * Uses the hashes of the views as keys and the hashes of the forms as * values. This is preferable over storing the objects directly, because * this way they can safely be discarded by the GC. * * @var array */ private $formsByView; public function __construct(FormDataExtractorInterface $dataExtractor) { $this->dataExtractor = $dataExtractor; $this->data = array( 'forms' => array(), 'nb_errors' => 0, ); } /** * Does nothing. The data is collected during the form event listeners. */ public function collect(Request $request, Response $response, \Exception $exception = null) { } /** * {@inheritdoc} */ public function associateFormWithView(FormInterface $form, FormView $view) { $this->formsByView[spl_object_hash($view)] = spl_object_hash($form); } /** * {@inheritdoc} */ public function collectConfiguration(FormInterface $form) { $hash = spl_object_hash($form); if (!isset($this->dataByForm[$hash])) { $this->dataByForm[$hash] = array(); } $this->dataByForm[$hash] = array_replace( $this->dataByForm[$hash], $this->dataExtractor->extractConfiguration($form) ); foreach ($form as $child) { $this->collectConfiguration($child); } } /** * {@inheritdoc} */ public function collectDefaultData(FormInterface $form) { $hash = spl_object_hash($form); if (!isset($this->dataByForm[$hash])) { $this->dataByForm[$hash] = array(); } $this->dataByForm[$hash] = array_replace( $this->dataByForm[$hash], $this->dataExtractor->extractDefaultData($form) ); foreach ($form as $child) { $this->collectDefaultData($child); } } /** * {@inheritdoc} */ public function collectSubmittedData(FormInterface $form) { $hash = spl_object_hash($form); if (!isset($this->dataByForm[$hash])) { $this->dataByForm[$hash] = array(); } $this->dataByForm[$hash] = array_replace( $this->dataByForm[$hash], $this->dataExtractor->extractSubmittedData($form) ); // Count errors if (isset($this->dataByForm[$hash]['errors'])) { $this->data['nb_errors'] += count($this->dataByForm[$hash]['errors']); } foreach ($form as $child) { $this->collectSubmittedData($child); } } /** * {@inheritdoc} */ public function collectViewVariables(FormView $view) { $hash = spl_object_hash($view); if (!isset($this->dataByView[$hash])) { $this->dataByView[$hash] = array(); } $this->dataByView[$hash] = array_replace( $this->dataByView[$hash], $this->dataExtractor->extractViewVariables($view) ); foreach ($view->children as $child) { $this->collectViewVariables($child); } } /** * {@inheritdoc} */ public function buildPreliminaryFormTree(FormInterface $form) { $this->data['forms'][$form->getName()] = array(); $this->recursiveBuildPreliminaryFormTree($form, $this->data['forms'][$form->getName()]); } /** * {@inheritdoc} */ public function buildFinalFormTree(FormInterface $form, FormView $view) { $this->data['forms'][$form->getName()] = array(); $this->recursiveBuildFinalFormTree($form, $view, $this->data['forms'][$form->getName()]); } /** * {@inheritDoc} */ public function getName() { return 'form'; } /** * {@inheritdoc} */ public function getData() { return $this->data; } private function recursiveBuildPreliminaryFormTree(FormInterface $form, &$output = null) { $hash = spl_object_hash($form); $output = isset($this->dataByForm[$hash]) ? $this->dataByForm[$hash] : array(); $output['children'] = array(); foreach ($form as $name => $child) { $output['children'][$name] = array(); $this->recursiveBuildPreliminaryFormTree($child, $output['children'][$name]); } } private function recursiveBuildFinalFormTree(FormInterface $form = null, FormView $view, &$output = null) { $viewHash = spl_object_hash($view); $formHash = null; if (null !== $form) { $formHash = spl_object_hash($form); } elseif (isset($this->formsByView[$viewHash])) { // The FormInterface instance of the CSRF token is never contained in // the FormInterface tree of the form, so we need to get the // corresponding FormInterface instance for its view in a different way $formHash = $this->formsByView[$viewHash]; } $output = isset($this->dataByView[$viewHash]) ? $this->dataByView[$viewHash] : array(); if (null !== $formHash) { $output = array_replace( $output, isset($this->dataByForm[$formHash]) ? $this->dataByForm[$formHash] : array() ); } $output['children'] = array(); foreach ($view->children as $name => $childView) { // The CSRF token, for example, is never added to the form tree. // It is only present in the view. $childForm = null !== $form && $form->has($name) ? $form->get($name) : null; $output['children'][$name] = array(); $this->recursiveBuildFinalFormTree($childForm, $childView, $output['children'][$name]); } } } PK]T ;Form/Extension/DataCollector/FormDataCollectorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; /** * Collects and structures information about forms. * * @since 2.4 * @author Bernhard Schussek */ interface FormDataCollectorInterface extends DataCollectorInterface { /** * Stores configuration data of the given form and its children. * * @param FormInterface $form A root form */ public function collectConfiguration(FormInterface $form); /** * Stores the default data of the given form and its children. * * @param FormInterface $form A root form */ public function collectDefaultData(FormInterface $form); /** * Stores the submitted data of the given form and its children. * * @param FormInterface $form A root form */ public function collectSubmittedData(FormInterface $form); /** * Stores the view variables of the given form view and its children. * * @param FormView $view A root form view */ public function collectViewVariables(FormView $view); /** * Specifies that the given objects represent the same conceptual form. * * @param FormInterface $form A form object * @param FormView $view A view object */ public function associateFormWithView(FormInterface $form, FormView $view); /** * Assembles the data collected about the given form and its children as * a tree-like data structure. * * The result can be queried using {@link getData()}. * * @param FormInterface $form A root form */ public function buildPreliminaryFormTree(FormInterface $form); /** * Assembles the data collected about the given form and its children as * a tree-like data structure. * * The result can be queried using {@link getData()}. * * Contrary to {@link buildPreliminaryFormTree()}, a {@link FormView} * object has to be passed. The tree structure of this view object will be * used for structuring the resulting data. That means, if a child is * present in the view, but not in the form, it will be present in the final * data array anyway. * * When {@link FormView} instances are present in the view tree, for which * no corresponding {@link FormInterface} objects can be found in the form * tree, only the view data will be included in the result. If a * corresponding {@link FormInterface} exists otherwise, call * {@link associateFormWithView()} before calling this method. * * @param FormInterface $form A root form * @param FormView $view A root view */ public function buildFinalFormTree(FormInterface $form, FormView $view); /** * Returns all collected data. * * @return array */ public function getData(); } PK]%`2Form/Extension/DataCollector/FormDataExtractor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; /** * Default implementation of {@link FormDataExtractorInterface}. * * @since 2.4 * @author Bernhard Schussek */ class FormDataExtractor implements FormDataExtractorInterface { /** * @var ValueExporter */ private $valueExporter; /** * Constructs a new data extractor. */ public function __construct(ValueExporter $valueExporter = null) { $this->valueExporter = $valueExporter ?: new ValueExporter(); } /** * {@inheritdoc} */ public function extractConfiguration(FormInterface $form) { $data = array( 'id' => $this->buildId($form), 'type' => $form->getConfig()->getType()->getName(), 'type_class' => get_class($form->getConfig()->getType()->getInnerType()), 'synchronized' => $this->valueExporter->exportValue($form->isSynchronized()), 'passed_options' => array(), 'resolved_options' => array(), ); foreach ($form->getConfig()->getAttribute('data_collector/passed_options', array()) as $option => $value) { $data['passed_options'][$option] = $this->valueExporter->exportValue($value); } foreach ($form->getConfig()->getOptions() as $option => $value) { $data['resolved_options'][$option] = $this->valueExporter->exportValue($value); } ksort($data['passed_options']); ksort($data['resolved_options']); return $data; } /** * {@inheritdoc} */ public function extractDefaultData(FormInterface $form) { $data = array( 'default_data' => array( 'norm' => $this->valueExporter->exportValue($form->getNormData()), ), 'submitted_data' => array(), ); if ($form->getData() !== $form->getNormData()) { $data['default_data']['model'] = $this->valueExporter->exportValue($form->getData()); } if ($form->getViewData() !== $form->getNormData()) { $data['default_data']['view'] = $this->valueExporter->exportValue($form->getViewData()); } return $data; } /** * {@inheritdoc} */ public function extractSubmittedData(FormInterface $form) { $data = array( 'submitted_data' => array( 'norm' => $this->valueExporter->exportValue($form->getNormData()), ), 'errors' => array(), ); if ($form->getViewData() !== $form->getNormData()) { $data['submitted_data']['view'] = $this->valueExporter->exportValue($form->getViewData()); } if ($form->getData() !== $form->getNormData()) { $data['submitted_data']['model'] = $this->valueExporter->exportValue($form->getData()); } foreach ($form->getErrors() as $error) { $data['errors'][] = array( 'message' => $error->getMessage(), ); } $data['synchronized'] = $this->valueExporter->exportValue($form->isSynchronized()); return $data; } /** * {@inheritdoc} */ public function extractViewVariables(FormView $view) { $data = array(); // Set the ID in case no FormInterface object was collected for this // view if (isset($view->vars['id'])) { $data['id'] = $view->vars['id']; } foreach ($view->vars as $varName => $value) { $data['view_vars'][$varName] = $this->valueExporter->exportValue($value); } ksort($data['view_vars']); return $data; } /** * Recursively builds an HTML ID for a form. * * @param FormInterface $form The form * * @return string The HTML ID */ private function buildId(FormInterface $form) { $id = $form->getName(); if (null !== $form->getParent()) { $id = $this->buildId($form->getParent()).'_'.$id; } return $id; } } PK]j= = >Form/Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\RequestHandlerInterface; use Symfony\Component\HttpFoundation\Request; /** * A request processor using the {@link Request} class of the HttpFoundation * component. * * @author Bernhard Schussek */ class HttpFoundationRequestHandler implements RequestHandlerInterface { /** * {@inheritdoc} */ public function handleRequest(FormInterface $form, $request = null) { if (!$request instanceof Request) { throw new UnexpectedTypeException($request, 'Symfony\Component\HttpFoundation\Request'); } $name = $form->getName(); $method = $form->getConfig()->getMethod(); if ($method !== $request->getMethod()) { return; } if ('GET' === $method) { if ('' === $name) { $data = $request->query->all(); } else { // Don't submit GET requests if the form's name does not exist // in the request if (!$request->query->has($name)) { return; } $data = $request->query->get($name); } } else { if ('' === $name) { $params = $request->request->all(); $files = $request->files->all(); } elseif ($request->request->has($name) || $request->files->has($name)) { $default = $form->getConfig()->getCompound() ? array() : null; $params = $request->request->get($name, $default); $files = $request->files->get($name, $default); } else { // Don't submit the form if it is not present in the request return; } if (is_array($params) && is_array($files)) { $data = array_replace_recursive($params, $files); } else { $data = $params ?: $files; } } // Don't auto-submit the form unless at least one field is present. if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) { return; } $form->submit($data, 'PATCH' !== $method); } } PK]PffFForm/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\FormBuilderInterface; /** * @author Bernhard Schussek */ class FormTypeHttpFoundationExtension extends AbstractTypeExtension { /** * @var BindRequestListener */ private $listener; /** * @var HttpFoundationRequestHandler */ private $requestHandler; public function __construct() { $this->listener = new BindRequestListener(); $this->requestHandler = new HttpFoundationRequestHandler(); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber($this->listener); $builder->setRequestHandler($this->requestHandler); } /** * {@inheritdoc} */ public function getExtendedType() { return 'form'; } } PK]䋧 CForm/Extension/HttpFoundation/EventListener/BindRequestListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; /** * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Pass the * Request instance to {@link Form::handleRequest()} instead. */ class BindRequestListener implements EventSubscriberInterface { public static function getSubscribedEvents() { // High priority in order to supersede other listeners return array(FormEvents::PRE_BIND => array('preBind', 128)); } public function preBind(FormEvent $event) { $form = $event->getForm(); /* @var Request $request */ $request = $event->getData(); // Only proceed if we actually deal with a Request if (!$request instanceof Request) { return; } // Uncomment this as soon as the deprecation note should be shown // trigger_error('Passing a Request instance to Form::submit() is deprecated since version 2.3 and will be disabled in 3.0. Call Form::process($request) instead.', E_USER_DEPRECATED); $name = $form->getConfig()->getName(); $default = $form->getConfig()->getCompound() ? array() : null; // Store the bound data in case of a post request switch ($request->getMethod()) { case 'POST': case 'PUT': case 'DELETE': case 'PATCH': if ('' === $name) { // Form bound without name $params = $request->request->all(); $files = $request->files->all(); } else { $params = $request->request->get($name, $default); $files = $request->files->get($name, $default); } if (is_array($params) && is_array($files)) { $data = array_replace_recursive($params, $files); } else { $data = $params ?: $files; } break; case 'GET': $data = '' === $name ? $request->query->all() : $request->query->get($name, $default); break; default: throw new LogicException(sprintf( 'The request method "%s" is not supported', $request->getMethod() )); } $event->setData($data); } } PK]Q9Form/Extension/HttpFoundation/HttpFoundationExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation; use Symfony\Component\Form\AbstractExtension; /** * Integrates the HttpFoundation component with the Form library. * * @author Bernhard Schussek */ class HttpFoundationExtension extends AbstractExtension { protected function loadTypeExtensions() { return array( new Type\FormTypeHttpFoundationExtension(), ); } } PK]  5Form/Extension/Core/DataMapper/PropertyPathMapper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataMapper; use Symfony\Component\Form\DataMapperInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; /** * A data mapper using property paths to read/write data. * * @author Bernhard Schussek */ class PropertyPathMapper implements DataMapperInterface { /** * @var PropertyAccessorInterface */ private $propertyAccessor; /** * Creates a new property path mapper. * * @param PropertyAccessorInterface $propertyAccessor */ public function __construct(PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } /** * {@inheritdoc} */ public function mapDataToForms($data, $forms) { $empty = null === $data || array() === $data; if (!$empty && !is_array($data) && !is_object($data)) { throw new UnexpectedTypeException($data, 'object, array or empty'); } foreach ($forms as $form) { $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); if (!$empty && null !== $propertyPath && $config->getMapped()) { $form->setData($this->propertyAccessor->getValue($data, $propertyPath)); } else { $form->setData($form->getConfig()->getData()); } } } /** * {@inheritdoc} */ public function mapFormsToData($forms, &$data) { if (null === $data) { return; } if (!is_array($data) && !is_object($data)) { throw new UnexpectedTypeException($data, 'object, array or empty'); } foreach ($forms as $form) { $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); // Write-back is disabled if the form is not synchronized (transformation failed), // if the form was not submitted and if the form is disabled (modification not allowed) if (null !== $propertyPath && $config->getMapped() && $form->isSubmitted() && $form->isSynchronized() && !$form->isDisabled()) { // If the field is of type DateTime and the data is the same skip the update to // keep the original object hash if ($form->getData() instanceof \DateTime && $form->getData() == $this->propertyAccessor->getValue($data, $propertyPath)) { continue; } // If the data is identical to the value in $data, we are // dealing with a reference if (!is_object($data) || !$config->getByReference() || $form->getData() !== $this->propertyAccessor->getValue($data, $propertyPath)) { $this->propertyAccessor->setValue($data, $propertyPath, $form->getData()); } } } } } PK]&PP'Form/Extension/Core/View/ChoiceView.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\View; /** * Represents a choice in templates. * * @author Bernhard Schussek */ class ChoiceView { /** * The original choice value. * * @var mixed */ public $data; /** * The view representation of the choice. * * @var string */ public $value; /** * The label displayed to humans. * * @var string */ public $label; /** * Creates a new ChoiceView. * * @param mixed $data The original choice. * @param string $value The view representation of the choice. * @param string $label The label displayed to humans. */ public function __construct($data, $value, $label) { $this->data = $data; $this->value = $value; $this->label = $label; } } PK]uƵ``(Form/Extension/Core/Type/IntegerType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class IntegerType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addViewTransformer( new IntegerToLocalizedStringTransformer( $options['precision'], $options['grouping'], $options['rounding_mode'] )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // default precision is locale specific (usually around 3) 'precision' => null, 'grouping' => false, // Integer cast rounds towards 0, so do the same when displaying fractions 'rounding_mode' => IntegerToLocalizedStringTransformer::ROUND_DOWN, 'compound' => false, )); $resolver->setAllowedValues(array( 'rounding_mode' => array( IntegerToLocalizedStringTransformer::ROUND_FLOOR, IntegerToLocalizedStringTransformer::ROUND_DOWN, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN, IntegerToLocalizedStringTransformer::ROUND_HALF_UP, IntegerToLocalizedStringTransformer::ROUND_UP, IntegerToLocalizedStringTransformer::ROUND_CEILING, ), )); } /** * {@inheritdoc} */ public function getName() { return 'integer'; } } PK]aLŢ(Form/Extension/Core/Type/CountryType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CountryType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getRegionBundle()->getCountryNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'country'; } } PK]DU'Form/Extension/Core/Type/SubmitType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\SubmitButtonTypeInterface; /** * A submit button. * * @author Bernhard Schussek */ class SubmitType extends AbstractType implements SubmitButtonTypeInterface { public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['clicked'] = $form->isClicked(); } /** * {@inheritdoc} */ public function getParent() { return 'button'; } /** * {@inheritdoc} */ public function getName() { return 'submit'; } } PK]8JJ'Form/Extension/Core/Type/SearchType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; class SearchType extends AbstractType { /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'search'; } } PK])Form/Extension/Core/Type/LanguageType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class LanguageType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getLanguageBundle()->getLanguageNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'language'; } } PK]a&Form/Extension/Core/Type/ResetType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\ButtonTypeInterface; /** * A reset button. * * @author Bernhard Schussek */ class ResetType extends AbstractType implements ButtonTypeInterface { /** * {@inheritdoc} */ public function getParent() { return 'button'; } /** * {@inheritdoc} */ public function getName() { return 'reset'; } } PK]Ѝ''Form/Extension/Core/Type/HiddenType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class HiddenType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // hidden fields cannot have a required attribute 'required' => false, // Pass errors to the parent 'error_bubbling' => true, 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'hidden'; } } PK] &'')Form/Extension/Core/Type/DateTimeType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\ReversedTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class DateTimeType extends AbstractType { const DEFAULT_DATE_FORMAT = \IntlDateFormatter::MEDIUM; const DEFAULT_TIME_FORMAT = \IntlDateFormatter::MEDIUM; /** * This is not quite the HTML5 format yet, because ICU lacks the * capability of parsing and generating RFC 3339 dates, which * are like the below pattern but with a timezone suffix. The * timezone suffix is * * * "Z" for UTC * * "(-|+)HH:mm" for other timezones (note the colon!) * * For more information see: * * http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax * http://www.w3.org/TR/html-markup/input.datetime.html * http://tools.ietf.org/html/rfc3339 * * An ICU ticket was created: * http://icu-project.org/trac/ticket/9421 * * It was supposedly fixed, but is not available in all PHP installations * yet. To temporarily circumvent this issue, DateTimeToRfc3339Transformer * is used when the format matches this constant. */ const HTML5_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"; private static $acceptedFormats = array( \IntlDateFormatter::FULL, \IntlDateFormatter::LONG, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, ); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $parts = array('year', 'month', 'day', 'hour'); $dateParts = array('year', 'month', 'day'); $timeParts = array('hour'); if ($options['with_minutes']) { $parts[] = 'minute'; $timeParts[] = 'minute'; } if ($options['with_seconds']) { $parts[] = 'second'; $timeParts[] = 'second'; } $dateFormat = is_int($options['date_format']) ? $options['date_format'] : self::DEFAULT_DATE_FORMAT; $timeFormat = self::DEFAULT_TIME_FORMAT; $calendar = \IntlDateFormatter::GREGORIAN; $pattern = is_string($options['format']) ? $options['format'] : null; if (!in_array($dateFormat, self::$acceptedFormats, true)) { throw new InvalidOptionsException('The "date_format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.'); } if ('single_text' === $options['widget']) { if (self::HTML5_FORMAT === $pattern) { $builder->addViewTransformer(new DateTimeToRfc3339Transformer( $options['model_timezone'], $options['view_timezone'] )); } else { $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( $options['model_timezone'], $options['view_timezone'], $dateFormat, $timeFormat, $calendar, $pattern )); } } else { // Only pass a subset of the options to children $dateOptions = array_intersect_key($options, array_flip(array( 'years', 'months', 'days', 'empty_value', 'required', 'translation_domain', ))); $timeOptions = array_intersect_key($options, array_flip(array( 'hours', 'minutes', 'seconds', 'with_minutes', 'with_seconds', 'empty_value', 'required', 'translation_domain', ))); if (null !== $options['date_widget']) { $dateOptions['widget'] = $options['date_widget']; } if (null !== $options['time_widget']) { $timeOptions['widget'] = $options['time_widget']; } if (null !== $options['date_format']) { $dateOptions['format'] = $options['date_format']; } $dateOptions['input'] = $timeOptions['input'] = 'array'; $dateOptions['error_bubbling'] = $timeOptions['error_bubbling'] = true; $builder ->addViewTransformer(new DataTransformerChain(array( new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts), new ArrayToPartsTransformer(array( 'date' => $dateParts, 'time' => $timeParts, )), ))) ->add('date', 'date', $dateOptions) ->add('time', 'time', $timeOptions) ; } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts) )); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['widget'] = $options['widget']; // Change the input to a HTML5 date input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { $view->vars['type'] = 'datetime'; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $compound = function (Options $options) { return $options['widget'] !== 'single_text'; }; // Defaults to the value of "widget" $dateWidget = function (Options $options) { return $options['widget']; }; // Defaults to the value of "widget" $timeWidget = function (Options $options) { return $options['widget']; }; $resolver->setDefaults(array( 'input' => 'datetime', 'model_timezone' => null, 'view_timezone' => null, 'format' => self::HTML5_FORMAT, 'date_format' => null, 'widget' => null, 'date_widget' => $dateWidget, 'time_widget' => $timeWidget, 'with_minutes' => true, 'with_seconds' => false, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. 'data_class' => null, 'compound' => $compound, )); // Don't add some defaults in order to preserve the defaults // set in DateType and TimeType $resolver->setOptional(array( 'empty_value', 'years', 'months', 'days', 'hours', 'minutes', 'seconds', )); $resolver->setAllowedValues(array( 'input' => array( 'datetime', 'string', 'timestamp', 'array', ), 'date_widget' => array( null, // inherit default from DateType 'single_text', 'text', 'choice', ), 'time_widget' => array( null, // inherit default from TimeType 'single_text', 'text', 'choice', ), // This option will overwrite "date_widget" and "time_widget" options 'widget' => array( null, // default, don't overwrite options 'single_text', 'text', 'choice', ), )); } /** * {@inheritdoc} */ public function getName() { return 'datetime'; } } PK]Goo%Form/Extension/Core/Type/FileType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FileType extends AbstractType { /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'type' => 'file', 'value' => '', )); } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $view ->vars['multipart'] = true ; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'compound' => false, 'data_class' => 'Symfony\Component\HttpFoundation\File\File', 'empty_data' => null, )); } /** * {@inheritdoc} */ public function getName() { return 'file'; } } PK]HH&Form/Extension/Core/Type/EmailType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; class EmailType extends AbstractType { /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'email'; } } PK]7pOLL&Form/Extension/Core/Type/RadioType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; class RadioType extends AbstractType { /** * {@inheritdoc} */ public function getParent() { return 'checkbox'; } /** * {@inheritdoc} */ public function getName() { return 'radio'; } } PK]9)Form/Extension/Core/Type/RepeatedType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class RepeatedType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { // Overwrite required option for child fields $options['first_options']['required'] = $options['required']; $options['second_options']['required'] = $options['required']; if (!isset($options['options']['error_bubbling'])) { $options['options']['error_bubbling'] = $options['error_bubbling']; } $builder ->addViewTransformer(new ValueToDuplicatesTransformer(array( $options['first_name'], $options['second_name'], ))) ->add($options['first_name'], $options['type'], array_merge($options['options'], $options['first_options'])) ->add($options['second_name'], $options['type'], array_merge($options['options'], $options['second_options'])) ; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'type' => 'text', 'options' => array(), 'first_options' => array(), 'second_options' => array(), 'first_name' => 'first', 'second_name' => 'second', 'error_bubbling' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'repeated'; } } PK]ٝGG%Form/Extension/Core/Type/BaseType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * Encapsulates common logic of {@link FormType} and {@link ButtonType}. * * This type does not appear in the form's type inheritance chain and as such * cannot be extended (via {@link FormTypeExtension}s) nor themed. * * @author Bernhard Schussek */ abstract class BaseType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->setDisabled($options['disabled']); $builder->setAutoInitialize($options['auto_initialize']); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $name = $form->getName(); $blockName = $options['block_name'] ?: $form->getName(); $translationDomain = $options['translation_domain']; if ($view->parent) { if ('' !== ($parentFullName = $view->parent->vars['full_name'])) { $id = sprintf('%s_%s', $view->parent->vars['id'], $name); $fullName = sprintf('%s[%s]', $parentFullName, $name); $uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName); } else { $id = $name; $fullName = $name; $uniqueBlockPrefix = '_'.$blockName; } if (!$translationDomain) { $translationDomain = $view->parent->vars['translation_domain']; } } else { $id = $name; $fullName = $name; $uniqueBlockPrefix = '_'.$blockName; // Strip leading underscores and digits. These are allowed in // form names, but not in HTML4 ID attributes. // http://www.w3.org/TR/html401/struct/global.html#adef-id $id = ltrim($id, '_0123456789'); } $blockPrefixes = array(); for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) { array_unshift($blockPrefixes, $type->getName()); } $blockPrefixes[] = $uniqueBlockPrefix; if (!$translationDomain) { $translationDomain = 'messages'; } $view->vars = array_replace($view->vars, array( 'form' => $view, 'id' => $id, 'name' => $name, 'full_name' => $fullName, 'disabled' => $form->isDisabled(), 'label' => $options['label'], 'multipart' => false, 'attr' => $options['attr'], 'block_prefixes' => $blockPrefixes, 'unique_block_prefix' => $uniqueBlockPrefix, 'translation_domain' => $translationDomain, // Using the block name here speeds up performance in collection // forms, where each entry has the same full block name. // Including the type is important too, because if rows of a // collection form have different types (dynamically), they should // be rendered differently. // https://github.com/symfony/symfony/issues/5038 'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(), )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'block_name' => null, 'disabled' => false, 'label' => null, 'attr' => array(), 'translation_domain' => null, 'auto_initialize' => true, )); $resolver->setAllowedTypes(array( 'attr' => 'array', )); } } PK]&ߏvv)Form/Extension/Core/Type/BirthdayType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class BirthdayType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'years' => range(date('Y') - 120, date('Y')), )); } /** * {@inheritdoc} */ public function getParent() { return 'date'; } /** * {@inheritdoc} */ public function getName() { return 'birthday'; } } PK]H?!a%Form/Extension/Core/Type/TimeType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\ReversedTransformer; use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class TimeType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $parts = array('hour'); $format = 'H'; if ($options['with_seconds'] && !$options['with_minutes']) { throw new InvalidConfigurationException('You can not disable minutes if you have enabled seconds.'); } if ($options['with_minutes']) { $format .= ':i'; $parts[] = 'minute'; } if ($options['with_seconds']) { $format .= ':s'; $parts[] = 'second'; } if ('single_text' === $options['widget']) { $builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format)); } else { $hourOptions = $minuteOptions = $secondOptions = array( 'error_bubbling' => true, ); if ('choice' === $options['widget']) { $hours = $minutes = array(); foreach ($options['hours'] as $hour) { $hours[$hour] = str_pad($hour, 2, '0', STR_PAD_LEFT); } // Only pass a subset of the options to children $hourOptions['choices'] = $hours; $hourOptions['empty_value'] = $options['empty_value']['hour']; if ($options['with_minutes']) { foreach ($options['minutes'] as $minute) { $minutes[$minute] = str_pad($minute, 2, '0', STR_PAD_LEFT); } $minuteOptions['choices'] = $minutes; $minuteOptions['empty_value'] = $options['empty_value']['minute']; } if ($options['with_seconds']) { $seconds = array(); foreach ($options['seconds'] as $second) { $seconds[$second] = str_pad($second, 2, '0', STR_PAD_LEFT); } $secondOptions['choices'] = $seconds; $secondOptions['empty_value'] = $options['empty_value']['second']; } // Append generic carry-along options foreach (array('required', 'translation_domain') as $passOpt) { $hourOptions[$passOpt] = $options[$passOpt]; if ($options['with_minutes']) { $minuteOptions[$passOpt] = $options[$passOpt]; } if ($options['with_seconds']) { $secondOptions[$passOpt] = $options[$passOpt]; } } } $builder->add('hour', $options['widget'], $hourOptions); if ($options['with_minutes']) { $builder->add('minute', $options['widget'], $minuteOptions); } if ($options['with_seconds']) { $builder->add('second', $options['widget'], $secondOptions); } $builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget'])); } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'H:i:s') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts) )); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'widget' => $options['widget'], 'with_minutes' => $options['with_minutes'], 'with_seconds' => $options['with_seconds'], )); if ('single_text' === $options['widget']) { $view->vars['type'] = 'time'; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $compound = function (Options $options) { return $options['widget'] !== 'single_text'; }; $emptyValue = $emptyValueDefault = function (Options $options) { return $options['required'] ? null : ''; }; $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) { if (is_array($emptyValue)) { $default = $emptyValueDefault($options); return array_merge( array('hour' => $default, 'minute' => $default, 'second' => $default), $emptyValue ); } return array( 'hour' => $emptyValue, 'minute' => $emptyValue, 'second' => $emptyValue ); }; $resolver->setDefaults(array( 'hours' => range(0, 23), 'minutes' => range(0, 59), 'seconds' => range(0, 59), 'widget' => 'choice', 'input' => 'datetime', 'with_minutes' => true, 'with_seconds' => false, 'model_timezone' => null, 'view_timezone' => null, 'empty_value' => $emptyValue, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. 'data_class' => null, 'compound' => $compound, )); $resolver->setNormalizers(array( 'empty_value' => $emptyValueNormalizer, )); $resolver->setAllowedValues(array( 'input' => array( 'datetime', 'string', 'timestamp', 'array', ), 'widget' => array( 'single_text', 'text', 'choice', ), )); } /** * {@inheritdoc} */ public function getName() { return 'time'; } } PK]M2\3,3,%Form/Extension/Core/Type/DateType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\ReversedTransformer; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; class DateType extends AbstractType { const DEFAULT_FORMAT = \IntlDateFormatter::MEDIUM; const HTML5_FORMAT = 'yyyy-MM-dd'; private static $acceptedFormats = array( \IntlDateFormatter::FULL, \IntlDateFormatter::LONG, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, ); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $dateFormat = is_int($options['format']) ? $options['format'] : self::DEFAULT_FORMAT; $timeFormat = \IntlDateFormatter::NONE; $calendar = \IntlDateFormatter::GREGORIAN; $pattern = is_string($options['format']) ? $options['format'] : null; if (!in_array($dateFormat, self::$acceptedFormats, true)) { throw new InvalidOptionsException('The "format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.'); } if (null !== $pattern && (false === strpos($pattern, 'y') || false === strpos($pattern, 'M') || false === strpos($pattern, 'd'))) { throw new InvalidOptionsException(sprintf('The "format" option should contain the letters "y", "M" and "d". Its current value is "%s".', $pattern)); } if ('single_text' === $options['widget']) { $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( $options['model_timezone'], $options['view_timezone'], $dateFormat, $timeFormat, $calendar, $pattern )); } else { $yearOptions = $monthOptions = $dayOptions = array( 'error_bubbling' => true, ); $formatter = new \IntlDateFormatter( \Locale::getDefault(), $dateFormat, $timeFormat, 'UTC', $calendar, $pattern ); $formatter->setLenient(false); if ('choice' === $options['widget']) { // Only pass a subset of the options to children $yearOptions['choices'] = $this->formatTimestamps($formatter, '/y+/', $this->listYears($options['years'])); $yearOptions['empty_value'] = $options['empty_value']['year']; $monthOptions['choices'] = $this->formatTimestamps($formatter, '/[M|L]+/', $this->listMonths($options['months'])); $monthOptions['empty_value'] = $options['empty_value']['month']; $dayOptions['choices'] = $this->formatTimestamps($formatter, '/d+/', $this->listDays($options['days'])); $dayOptions['empty_value'] = $options['empty_value']['day']; } // Append generic carry-along options foreach (array('required', 'translation_domain') as $passOpt) { $yearOptions[$passOpt] = $monthOptions[$passOpt] = $dayOptions[$passOpt] = $options[$passOpt]; } $builder ->add('year', $options['widget'], $yearOptions) ->add('month', $options['widget'], $monthOptions) ->add('day', $options['widget'], $dayOptions) ->addViewTransformer(new DateTimeToArrayTransformer( $options['model_timezone'], $options['view_timezone'], array('year', 'month', 'day') )) ->setAttribute('formatter', $formatter) ; } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'Y-m-d') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], array('year', 'month', 'day')) )); } } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $view->vars['widget'] = $options['widget']; // Change the input to a HTML5 date input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { $view->vars['type'] = 'date'; } if ($form->getConfig()->hasAttribute('formatter')) { $pattern = $form->getConfig()->getAttribute('formatter')->getPattern(); // remove special characters unless the format was explicitly specified if (!is_string($options['format'])) { $pattern = preg_replace('/[^yMd]+/', '', $pattern); } // set right order with respect to locale (e.g.: de_DE=dd.MM.yy; en_US=M/d/yy) // lookup various formats at http://userguide.icu-project.org/formatparse/datetime if (preg_match('/^([yMd]+)[^yMd]*([yMd]+)[^yMd]*([yMd]+)$/', $pattern)) { $pattern = preg_replace(array('/y+/', '/M+/', '/d+/'), array('{{ year }}', '{{ month }}', '{{ day }}'), $pattern); } else { // default fallback $pattern = '{{ year }}{{ month }}{{ day }}'; } $view->vars['date_pattern'] = $pattern; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $compound = function (Options $options) { return $options['widget'] !== 'single_text'; }; $emptyValue = $emptyValueDefault = function (Options $options) { return $options['required'] ? null : ''; }; $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) { if (is_array($emptyValue)) { $default = $emptyValueDefault($options); return array_merge( array('year' => $default, 'month' => $default, 'day' => $default), $emptyValue ); } return array( 'year' => $emptyValue, 'month' => $emptyValue, 'day' => $emptyValue ); }; $format = function (Options $options) { return $options['widget'] === 'single_text' ? DateType::HTML5_FORMAT : DateType::DEFAULT_FORMAT; }; $resolver->setDefaults(array( 'years' => range(date('Y') - 5, date('Y') + 5), 'months' => range(1, 12), 'days' => range(1, 31), 'widget' => 'choice', 'input' => 'datetime', 'format' => $format, 'model_timezone' => null, 'view_timezone' => null, 'empty_value' => $emptyValue, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. 'data_class' => null, 'compound' => $compound, )); $resolver->setNormalizers(array( 'empty_value' => $emptyValueNormalizer, )); $resolver->setAllowedValues(array( 'input' => array( 'datetime', 'string', 'timestamp', 'array', ), 'widget' => array( 'single_text', 'text', 'choice', ), )); $resolver->setAllowedTypes(array( 'format' => array('int', 'string'), )); } /** * {@inheritdoc} */ public function getName() { return 'date'; } private function formatTimestamps(\IntlDateFormatter $formatter, $regex, array $timestamps) { $pattern = $formatter->getPattern(); $timezone = $formatter->getTimezoneId(); if ($setTimeZone = method_exists($formatter, 'setTimeZone')) { $formatter->setTimeZone('UTC'); } else { $formatter->setTimeZoneId('UTC'); } if (preg_match($regex, $pattern, $matches)) { $formatter->setPattern($matches[0]); foreach ($timestamps as $key => $timestamp) { $timestamps[$key] = $formatter->format($timestamp); } // I'd like to clone the formatter above, but then we get a // segmentation fault, so let's restore the old state instead $formatter->setPattern($pattern); } if ($setTimeZone) { $formatter->setTimeZone($timezone); } else { $formatter->setTimeZoneId($timezone); } return $timestamps; } private function listYears(array $years) { $result = array(); foreach ($years as $year) { if (false !== $y = gmmktime(0, 0, 0, 6, 15, $year)) { $result[$year] = $y; } } return $result; } private function listMonths(array $months) { $result = array(); foreach ($months as $month) { $result[$month] = gmmktime(0, 0, 0, $month, 15); } return $result; } private function listDays(array $days) { $result = array(); foreach ($days as $day) { $result[$day] = gmmktime(0, 0, 0, 5, $day); } return $result; } } PK]옇)Form/Extension/Core/Type/PasswordType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class PasswordType extends AbstractType { /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { if ($options['always_empty'] || !$form->isSubmitted()) { $view->vars['value'] = ''; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'always_empty' => true, 'trim' => false, )); } /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'password'; } } PK]T;%Form/Extension/Core/Type/TextType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class TextType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'text'; } } PK]q$Form/Extension/Core/Type/UrlType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class UrlType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber(new FixUrlProtocolListener($options['default_protocol'])); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'default_protocol' => 'http', )); } /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'url'; } } PK]5S &Form/Extension/Core/Type/MoneyType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class MoneyType extends AbstractType { protected static $patterns = array(); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->addViewTransformer(new MoneyToLocalizedStringTransformer( $options['precision'], $options['grouping'], null, $options['divisor'] )) ; } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['money_pattern'] = self::getPattern($options['currency']); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'precision' => 2, 'grouping' => false, 'divisor' => 1, 'currency' => 'EUR', 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'money'; } /** * Returns the pattern for this locale * * The pattern contains the placeholder "{{ widget }}" where the HTML tag should * be inserted */ protected static function getPattern($currency) { if (!$currency) { return '{{ widget }}'; } $locale = \Locale::getDefault(); if (!isset(self::$patterns[$locale])) { self::$patterns[$locale] = array(); } if (!isset(self::$patterns[$locale][$currency])) { $format = new \NumberFormatter($locale, \NumberFormatter::CURRENCY); $pattern = $format->formatCurrency('123', $currency); // the spacings between currency symbol and number are ignored, because // a single space leads to better readability in combination with input // fields // the regex also considers non-break spaces (0xC2 or 0xA0 in UTF-8) preg_match('/^([^\s\xc2\xa0]*)[\s\xc2\xa0]*123(?:[,.]0+)?[\s\xc2\xa0]*([^\s\xc2\xa0]*)$/u', $pattern, $matches); if (!empty($matches[1])) { self::$patterns[$locale][$currency] = $matches[1].' {{ widget }}'; } elseif (!empty($matches[2])) { self::$patterns[$locale][$currency] = '{{ widget }} '.$matches[2]; } else { self::$patterns[$locale][$currency] = '{{ widget }}'; } } return self::$patterns[$locale][$currency]; } } PK]tII)Form/Extension/Core/Type/TextareaType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; class TextareaType extends AbstractType { /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['pattern'] = null; } /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'textarea'; } } PK]/++'Form/Extension/Core/Type/ChoiceType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener; use Symfony\Component\Form\Extension\Core\EventListener\FixCheckboxInputListener; use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToBooleanArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToBooleanArrayTransformer; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class ChoiceType extends AbstractType { /** * Caches created choice lists. * @var array */ private $choiceListCache = array(); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { if (!$options['choice_list'] && !is_array($options['choices']) && !$options['choices'] instanceof \Traversable) { throw new LogicException('Either the option "choices" or "choice_list" must be set.'); } if ($options['expanded']) { // Initialize all choices before doing the index check below. // This helps in cases where index checks are optimized for non // initialized choice lists. For example, when using an SQL driver, // the index check would read in one SQL query and the initialization // requires another SQL query. When the initialization is done first, // one SQL query is sufficient. $preferredViews = $options['choice_list']->getPreferredViews(); $remainingViews = $options['choice_list']->getRemainingViews(); // Check if the choices already contain the empty value // Only add the empty value option if this is not the case if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) { $placeholderView = new ChoiceView(null, '', $options['empty_value']); // "placeholder" is a reserved index // see also ChoiceListInterface::getIndicesForChoices() $this->addSubForms($builder, array('placeholder' => $placeholderView), $options); } $this->addSubForms($builder, $preferredViews, $options); $this->addSubForms($builder, $remainingViews, $options); if ($options['multiple']) { $builder->addViewTransformer(new ChoicesToBooleanArrayTransformer($options['choice_list'])); $builder->addEventSubscriber(new FixCheckboxInputListener($options['choice_list']), 10); } else { $builder->addViewTransformer(new ChoiceToBooleanArrayTransformer($options['choice_list'], $builder->has('placeholder'))); $builder->addEventSubscriber(new FixRadioInputListener($options['choice_list'], $builder->has('placeholder')), 10); } } else { if ($options['multiple']) { $builder->addViewTransformer(new ChoicesToValuesTransformer($options['choice_list'])); } else { $builder->addViewTransformer(new ChoiceToValueTransformer($options['choice_list'])); } } if ($options['multiple'] && $options['by_reference']) { // Make sure the collection created during the client->norm // transformation is merged back into the original collection $builder->addEventSubscriber(new MergeCollectionListener(true, true)); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'multiple' => $options['multiple'], 'expanded' => $options['expanded'], 'preferred_choices' => $options['choice_list']->getPreferredViews(), 'choices' => $options['choice_list']->getRemainingViews(), 'separator' => '-------------------', 'empty_value' => null, )); // The decision, whether a choice is selected, is potentially done // thousand of times during the rendering of a template. Provide a // closure here that is optimized for the value of the form, to // avoid making the type check inside the closure. if ($options['multiple']) { $view->vars['is_selected'] = function ($choice, array $values) { return false !== array_search($choice, $values, true); }; } else { $view->vars['is_selected'] = function ($choice, $value) { return $choice === $value; }; } // Check if the choices already contain the empty value $view->vars['empty_value_in_choices'] = 0 !== count($options['choice_list']->getChoicesForValues(array(''))); // Only add the empty value option if this is not the case if (null !== $options['empty_value'] && !$view->vars['empty_value_in_choices']) { $view->vars['empty_value'] = $options['empty_value']; } if ($options['multiple'] && !$options['expanded']) { // Add "[]" to the name in case a select tag with multiple options is // displayed. Otherwise only one of the selected options is sent in the // POST request. $view->vars['full_name'] = $view->vars['full_name'].'[]'; } } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { if ($options['expanded']) { // Radio buttons should have the same name as the parent $childName = $view->vars['full_name']; // Checkboxes should append "[]" to allow multiple selection if ($options['multiple']) { $childName .= '[]'; } foreach ($view as $childView) { $childView->vars['full_name'] = $childName; } } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $choiceListCache =& $this->choiceListCache; $choiceList = function (Options $options) use (&$choiceListCache) { // Harden against NULL values (like in EntityType and ModelType) $choices = null !== $options['choices'] ? $options['choices'] : array(); // Reuse existing choice lists in order to increase performance $hash = hash('sha256', json_encode(array($choices, $options['preferred_choices']))); if (!isset($choiceListCache[$hash])) { $choiceListCache[$hash] = new SimpleChoiceList($choices, $options['preferred_choices']); } return $choiceListCache[$hash]; }; $emptyData = function (Options $options) { if ($options['multiple'] || $options['expanded']) { return array(); } return ''; }; $emptyValue = function (Options $options) { return $options['required'] ? null : ''; }; $emptyValueNormalizer = function (Options $options, $emptyValue) { if ($options['multiple']) { // never use an empty value for this case return null; } elseif (false === $emptyValue) { // an empty value should be added but the user decided otherwise return null; } elseif ($options['expanded'] && '' === $emptyValue) { // never use an empty label for radio buttons return 'None'; } // empty value has been set explicitly return $emptyValue; }; $compound = function (Options $options) { return $options['expanded']; }; $resolver->setDefaults(array( 'multiple' => false, 'expanded' => false, 'choice_list' => $choiceList, 'choices' => array(), 'preferred_choices' => array(), 'empty_data' => $emptyData, 'empty_value' => $emptyValue, 'error_bubbling' => false, 'compound' => $compound, // The view data is always a string, even if the "data" option // is manually set to an object. // See https://github.com/symfony/symfony/pull/5582 'data_class' => null, )); $resolver->setNormalizers(array( 'empty_value' => $emptyValueNormalizer, )); $resolver->setAllowedTypes(array( 'choice_list' => array('null', 'Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface'), )); } /** * {@inheritdoc} */ public function getName() { return 'choice'; } /** * Adds the sub fields for an expanded choice field. * * @param FormBuilderInterface $builder The form builder. * @param array $choiceViews The choice view objects. * @param array $options The build options. */ private function addSubForms(FormBuilderInterface $builder, array $choiceViews, array $options) { foreach ($choiceViews as $i => $choiceView) { if (is_array($choiceView)) { // Flatten groups $this->addSubForms($builder, $choiceView, $options); } else { $choiceOpts = array( 'value' => $choiceView->value, 'label' => $choiceView->label, 'translation_domain' => $options['translation_domain'], ); if ($options['multiple']) { $choiceType = 'checkbox'; // The user can check 0 or more checkboxes. If required // is true, he is required to check all of them. $choiceOpts['required'] = false; } else { $choiceType = 'radio'; } $builder->add($i, $choiceType, $choiceOpts); } } } } PK]Ci'Form/Extension/Core/Type/NumberType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class NumberType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addViewTransformer(new NumberToLocalizedStringTransformer( $options['precision'], $options['grouping'], $options['rounding_mode'] )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // default precision is locale specific (usually around 3) 'precision' => null, 'grouping' => false, 'rounding_mode' => NumberToLocalizedStringTransformer::ROUND_HALF_UP, 'compound' => false, )); $resolver->setAllowedValues(array( 'rounding_mode' => array( NumberToLocalizedStringTransformer::ROUND_FLOOR, NumberToLocalizedStringTransformer::ROUND_DOWN, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN, NumberToLocalizedStringTransformer::ROUND_HALF_UP, NumberToLocalizedStringTransformer::ROUND_UP, NumberToLocalizedStringTransformer::ROUND_CEILING, ), )); } /** * {@inheritdoc} */ public function getName() { return 'number'; } } PK]:y  %Form/Extension/Core/Type/FormType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; class FormType extends BaseType { /** * @var PropertyAccessorInterface */ private $propertyAccessor; public function __construct(PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { parent::buildForm($builder, $options); $isDataOptionSet = array_key_exists('data', $options); $builder ->setRequired($options['required']) ->setErrorBubbling($options['error_bubbling']) ->setEmptyData($options['empty_data']) ->setPropertyPath($options['property_path']) ->setMapped($options['mapped']) ->setByReference($options['by_reference']) ->setInheritData($options['inherit_data']) ->setCompound($options['compound']) ->setData($isDataOptionSet ? $options['data'] : null) ->setDataLocked($isDataOptionSet) ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null) ->setMethod($options['method']) ->setAction($options['action']) ; if ($options['trim']) { $builder->addEventSubscriber(new TrimListener()); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { parent::buildView($view, $form, $options); $name = $form->getName(); $readOnly = $options['read_only']; if ($view->parent) { if ('' === $name) { throw new LogicException('Form node with empty name can be used only as root form node.'); } // Complex fields are read-only if they themselves or their parents are. if (!$readOnly) { $readOnly = $view->parent->vars['read_only']; } } $view->vars = array_replace($view->vars, array( 'read_only' => $readOnly, 'errors' => $form->getErrors(), 'valid' => $form->isSubmitted() ? $form->isValid() : true, 'value' => $form->getViewData(), 'data' => $form->getNormData(), 'required' => $form->isRequired(), 'max_length' => $options['max_length'], 'pattern' => $options['pattern'], 'size' => null, 'label_attr' => $options['label_attr'], 'compound' => $form->getConfig()->getCompound(), 'method' => $form->getConfig()->getMethod(), 'action' => $form->getConfig()->getAction(), 'submitted' => $form->isSubmitted(), )); } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $multipart = false; foreach ($view->children as $child) { if ($child->vars['multipart']) { $multipart = true; break; } } $view->vars['multipart'] = $multipart; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { parent::setDefaultOptions($resolver); // Derive "data_class" option from passed "data" object $dataClass = function (Options $options) { return isset($options['data']) && is_object($options['data']) ? get_class($options['data']) : null; }; // Derive "empty_data" closure from "data_class" option $emptyData = function (Options $options) { $class = $options['data_class']; if (null !== $class) { return function (FormInterface $form) use ($class) { return $form->isEmpty() && !$form->isRequired() ? null : new $class(); }; } return function (FormInterface $form) { return $form->getConfig()->getCompound() ? array() : ''; }; }; // For any form that is not represented by a single HTML control, // errors should bubble up by default $errorBubbling = function (Options $options) { return $options['compound']; }; // BC with old "virtual" option $inheritData = function (Options $options) { if (null !== $options['virtual']) { // Uncomment this as soon as the deprecation note should be shown // trigger_error('The form option "virtual" is deprecated since version 2.3 and will be removed in 3.0. Use "inherit_data" instead.', E_USER_DEPRECATED); return $options['virtual']; } return false; }; // If data is given, the form is locked to that data // (independent of its value) $resolver->setOptional(array( 'data', )); $resolver->setDefaults(array( 'data_class' => $dataClass, 'empty_data' => $emptyData, 'trim' => true, 'required' => true, 'read_only' => false, 'max_length' => null, 'pattern' => null, 'property_path' => null, 'mapped' => true, 'by_reference' => true, 'error_bubbling' => $errorBubbling, 'label_attr' => array(), 'virtual' => null, 'inherit_data' => $inheritData, 'compound' => true, 'method' => 'POST', // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) // section 4.2., empty URIs are considered same-document references 'action' => '', )); $resolver->setAllowedTypes(array( 'label_attr' => 'array', )); } /** * {@inheritdoc} */ public function getParent() { return null; } /** * {@inheritdoc} */ public function getName() { return 'form'; } } PK]h'Form/Extension/Core/Type/ButtonType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\ButtonTypeInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * A form button. * * @author Bernhard Schussek */ class ButtonType extends BaseType implements ButtonTypeInterface { /** * {@inheritdoc} */ public function getParent() { return null; } /** * {@inheritdoc} */ public function getName() { return 'button'; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { parent::setDefaultOptions($resolver); $resolver->setDefaults(array( 'auto_initialize' => false, )); } } PK]񍢸)Form/Extension/Core/Type/CurrencyType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CurrencyType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getCurrencyBundle()->getCurrencyNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'currency'; } } PK]Z^^(Form/Extension/Core/Type/PercentType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class PercentType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addViewTransformer(new PercentToLocalizedStringTransformer($options['precision'], $options['type'])); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'precision' => 0, 'type' => 'fractional', 'compound' => false, )); $resolver->setAllowedValues(array( 'type' => array( 'fractional', 'integer', ), )); } /** * {@inheritdoc} */ public function getName() { return 'percent'; } } PK]D'Form/Extension/Core/Type/LocaleType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\Locale\Locale; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class LocaleType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getLocaleBundle()->getLocaleNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'locale'; } } PK]_LL)Form/Extension/Core/Type/TimezoneType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class TimezoneType extends AbstractType { /** * Stores the available timezone choices * @var array */ private static $timezones; /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => self::getTimezones(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'timezone'; } /** * Returns the timezone choices. * * The choices are generated from the ICU function * \DateTimeZone::listIdentifiers(). They are cached during a single request, * so multiple timezone fields on the same page don't lead to unnecessary * overhead. * * @return array The timezone choices */ public static function getTimezones() { if (null === static::$timezones) { static::$timezones = array(); foreach (\DateTimeZone::listIdentifiers() as $timezone) { $parts = explode('/', $timezone); if (count($parts) > 2) { $region = $parts[0]; $name = $parts[1].' - '.$parts[2]; } elseif (count($parts) > 1) { $region = $parts[0]; $name = $parts[1]; } else { $region = 'Other'; $name = $parts[0]; } static::$timezones[$region][$timezone] = str_replace('_', ' ', $name); } } return static::$timezones; } } PK]TT)Form/Extension/Core/Type/CheckboxType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CheckboxType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { // Unlike in other types, where the data is NULL by default, it // needs to be a Boolean here. setData(null) is not acceptable // for checkboxes and radio buttons (unless a custom model // transformer handles this case). // We cannot solve this case via overriding the "data" option, because // doing so also calls setDataLocked(true). $builder->setData(isset($options['data']) ? $options['data'] : false); $builder->addViewTransformer(new BooleanToStringTransformer($options['value'])); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'value' => $options['value'], 'checked' => null !== $form->getViewData(), )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $emptyData = function (FormInterface $form, $viewData) { return $viewData; }; $resolver->setDefaults(array( 'value' => '1', 'empty_data' => $emptyData, 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'checkbox'; } } PK][Gԃ +Form/Extension/Core/Type/CollectionType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CollectionType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { if ($options['allow_add'] && $options['prototype']) { $prototype = $builder->create($options['prototype_name'], $options['type'], array_replace(array( 'label' => $options['prototype_name'].'label__', ), $options['options'])); $builder->setAttribute('prototype', $prototype->getForm()); } $resizeListener = new ResizeFormListener( $options['type'], $options['options'], $options['allow_add'], $options['allow_delete'] ); $builder->addEventSubscriber($resizeListener); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'allow_add' => $options['allow_add'], 'allow_delete' => $options['allow_delete'], )); if ($form->getConfig()->hasAttribute('prototype')) { $view->vars['prototype'] = $form->getConfig()->getAttribute('prototype')->createView($view); } } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { if ($form->getConfig()->hasAttribute('prototype') && $view->vars['prototype']->vars['multipart']) { $view->vars['multipart'] = true; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $optionsNormalizer = function (Options $options, $value) { $value['block_name'] = 'entry'; return $value; }; $resolver->setDefaults(array( 'allow_add' => false, 'allow_delete' => false, 'prototype' => true, 'prototype_name' => '__name__', 'type' => 'text', 'options' => array(), )); $resolver->setNormalizers(array( 'options' => $optionsNormalizer, )); } /** * {@inheritdoc} */ public function getName() { return 'collection'; } } PK])b""LForm/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a normalized time and a localized time string * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer { private $dateFormat; private $timeFormat; private $pattern; private $calendar; /** * Constructor. * * @see BaseDateTimeTransformer::formats for available format options * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * @param integer $dateFormat The date format * @param integer $timeFormat The time format * @param integer $calendar One of the \IntlDateFormatter calendar constants * @param string $pattern A pattern to pass to \IntlDateFormatter * * @throws UnexpectedTypeException If a format is not supported or if a timezone is not a string */ public function __construct($inputTimezone = null, $outputTimezone = null, $dateFormat = null, $timeFormat = null, $calendar = \IntlDateFormatter::GREGORIAN, $pattern = null) { parent::__construct($inputTimezone, $outputTimezone); if (null === $dateFormat) { $dateFormat = \IntlDateFormatter::MEDIUM; } if (null === $timeFormat) { $timeFormat = \IntlDateFormatter::SHORT; } if (!in_array($dateFormat, self::$formats, true)) { throw new UnexpectedTypeException($dateFormat, implode('", "', self::$formats)); } if (!in_array($timeFormat, self::$formats, true)) { throw new UnexpectedTypeException($timeFormat, implode('", "', self::$formats)); } $this->dateFormat = $dateFormat; $this->timeFormat = $timeFormat; $this->calendar = $calendar; $this->pattern = $pattern; } /** * Transforms a normalized date into a localized date string/array. * * @param \DateTime $dateTime Normalized date. * * @return string|array Localized date string/array. * * @throws TransformationFailedException If the given value is not an instance * of \DateTime or if the date could not * be transformed. */ public function transform($dateTime) { if (null === $dateTime) { return ''; } if (!$dateTime instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } // convert time to UTC before passing it to the formatter $dateTime = clone $dateTime; if ('UTC' !== $this->inputTimezone) { $dateTime->setTimezone(new \DateTimeZone('UTC')); } $value = $this->getIntlDateFormatter()->format((int) $dateTime->format('U')); if (intl_get_error_code() != 0) { throw new TransformationFailedException(intl_get_error_message()); } return $value; } /** * Transforms a localized date string/array into a normalized date. * * @param string|array $value Localized date string/array * * @return \DateTime Normalized date * * @throws TransformationFailedException if the given value is not a string, * if the date could not be parsed or * if the input timezone is not supported */ public function reverseTransform($value) { if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $value) { return null; } $timestamp = $this->getIntlDateFormatter()->parse($value); if (intl_get_error_code() != 0) { throw new TransformationFailedException(intl_get_error_message()); } try { // read timestamp into DateTime object - the formatter delivers in UTC $dateTime = new \DateTime(sprintf('@%s UTC', $timestamp)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } if ('UTC' !== $this->inputTimezone) { try { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } } return $dateTime; } /** * Returns a preconfigured IntlDateFormatter instance * * @return \IntlDateFormatter */ protected function getIntlDateFormatter() { $dateFormat = $this->dateFormat; $timeFormat = $this->timeFormat; $timezone = $this->outputTimezone; $calendar = $this->calendar; $pattern = $this->pattern; $intlDateFormatter = new \IntlDateFormatter(\Locale::getDefault(), $dateFormat, $timeFormat, $timezone, $calendar, $pattern); $intlDateFormatter->setLenient(false); return $intlDateFormatter; } } PK]c8V <Form/Extension/Core/DataTransformer/DataTransformerChain.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Passes a value through multiple value transformers * * @author Bernhard Schussek */ class DataTransformerChain implements DataTransformerInterface { /** * The value transformers * @var DataTransformerInterface[] */ protected $transformers; /** * Uses the given value transformers to transform values * * @param array $transformers */ public function __construct(array $transformers) { $this->transformers = $transformers; } /** * Passes the value through the transform() method of all nested transformers * * The transformers receive the value in the same order as they were passed * to the constructor. Each transformer receives the result of the previous * transformer as input. The output of the last transformer is returned * by this method. * * @param mixed $value The original value * * @return mixed The transformed value * * @throws TransformationFailedException */ public function transform($value) { foreach ($this->transformers as $transformer) { $value = $transformer->transform($value); } return $value; } /** * Passes the value through the reverseTransform() method of all nested * transformers * * The transformers receive the value in the reverse order as they were passed * to the constructor. Each transformer receives the result of the previous * transformer as input. The output of the last transformer is returned * by this method. * * @param mixed $value The transformed value * * @return mixed The reverse-transformed value * * @throws TransformationFailedException */ public function reverseTransform($value) { for ($i = count($this->transformers) - 1; $i >= 0; --$i) { $value = $this->transformers[$i]->reverseTransform($value); } return $value; } } PK]/C?Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; abstract class BaseDateTimeTransformer implements DataTransformerInterface { protected static $formats = array( \IntlDateFormatter::NONE, \IntlDateFormatter::FULL, \IntlDateFormatter::LONG, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, ); protected $inputTimezone; protected $outputTimezone; /** * Constructor. * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * * @throws UnexpectedTypeException if a timezone is not a string * @throws InvalidArgumentException if a timezone is not valid */ public function __construct($inputTimezone = null, $outputTimezone = null) { if (!is_string($inputTimezone) && null !== $inputTimezone) { throw new UnexpectedTypeException($inputTimezone, 'string'); } if (!is_string($outputTimezone) && null !== $outputTimezone) { throw new UnexpectedTypeException($outputTimezone, 'string'); } $this->inputTimezone = $inputTimezone ?: date_default_timezone_get(); $this->outputTimezone = $outputTimezone ?: date_default_timezone_get(); // Check if input and output timezones are valid try { new \DateTimeZone($this->inputTimezone); } catch (\Exception $e) { throw new InvalidArgumentException(sprintf('Input timezone is invalid: %s.', $this->inputTimezone), $e->getCode(), $e); } try { new \DateTimeZone($this->outputTimezone); } catch (\Exception $e) { throw new InvalidArgumentException(sprintf('Output timezone is invalid: %s.', $this->outputTimezone), $e->getCode(), $e); } } } PK];ddKForm/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a normalized format (integer or float) and a percentage value. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class PercentToLocalizedStringTransformer implements DataTransformerInterface { const FRACTIONAL = 'fractional'; const INTEGER = 'integer'; protected static $types = array( self::FRACTIONAL, self::INTEGER, ); private $type; private $precision; /** * Constructor. * * @see self::$types for a list of supported types * * @param integer $precision The precision * @param string $type One of the supported types * * @throws UnexpectedTypeException if the given value of type is unknown */ public function __construct($precision = null, $type = null) { if (null === $precision) { $precision = 0; } if (null === $type) { $type = self::FRACTIONAL; } if (!in_array($type, self::$types, true)) { throw new UnexpectedTypeException($type, implode('", "', self::$types)); } $this->type = $type; $this->precision = $precision; } /** * Transforms between a normalized format (integer or float) into a percentage value. * * @param number $value Normalized value * * @return number Percentage value * * @throws TransformationFailedException If the given value is not numeric or * if the value could not be transformed. */ public function transform($value) { if (null === $value) { return ''; } if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } if (self::FRACTIONAL == $this->type) { $value *= 100; } $formatter = $this->getNumberFormatter(); $value = $formatter->format($value); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } // replace the UTF-8 non break spaces return $value; } /** * Transforms between a percentage value into a normalized format (integer or float). * * @param number $value Percentage value. * * @return number Normalized value. * * @throws TransformationFailedException If the given value is not a string or * if the value could not be transformed. */ public function reverseTransform($value) { if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $value) { return null; } $formatter = $this->getNumberFormatter(); // replace normal spaces so that the formatter can read them $value = $formatter->parse(str_replace(' ', ' ', $value)); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } if (self::FRACTIONAL == $this->type) { $value /= 100; } return $value; } /** * Returns a preconfigured \NumberFormatter instance * * @return \NumberFormatter */ protected function getNumberFormatter() { $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL); $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->precision); return $formatter; } } PK]H  ?Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ArrayToPartsTransformer implements DataTransformerInterface { private $partMapping; public function __construct(array $partMapping) { $this->partMapping = $partMapping; } public function transform($array) { if (null === $array) { $array = array(); } if (!is_array($array) ) { throw new TransformationFailedException('Expected an array.'); } $result = array(); foreach ($this->partMapping as $partKey => $originalKeys) { if (empty($array)) { $result[$partKey] = null; } else { $result[$partKey] = array_intersect_key($array, array_flip($originalKeys)); } } return $result; } public function reverseTransform($array) { if (!is_array($array) ) { throw new TransformationFailedException('Expected an array.'); } $result = array(); $emptyKeys = array(); foreach ($this->partMapping as $partKey => $originalKeys) { if (!empty($array[$partKey])) { foreach ($originalKeys as $originalKey) { if (isset($array[$partKey][$originalKey])) { $result[$originalKey] = $array[$partKey][$originalKey]; } } } else { $emptyKeys[] = $partKey; } } if (count($emptyKeys) > 0) { if (count($emptyKeys) === count($this->partMapping)) { // All parts empty return null; } throw new TransformationFailedException( sprintf('The keys "%s" should not be empty', implode('", "', $emptyKeys) )); } return $result; } } PK]ggBForm/Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * @author Bernhard Schussek */ class ChoicesToValuesTransformer implements DataTransformerInterface { private $choiceList; /** * Constructor. * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } /** * @param array $array * * @return array * * @throws TransformationFailedException If the given value is not an array. */ public function transform($array) { if (null === $array) { return array(); } if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } return $this->choiceList->getValuesForChoices($array); } /** * @param array $array * * @return array * * @throws TransformationFailedException If the given value is not an array * or if no matching choice could be * found for some given value. */ public function reverseTransform($array) { if (null === $array) { return array(); } if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } $choices = $this->choiceList->getChoicesForValues($array); if (count($choices) !== count($array)) { throw new TransformationFailedException('Could not find all matching choices for the given values'); } return $choices; } } PK]  DForm/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ValueToDuplicatesTransformer implements DataTransformerInterface { private $keys; public function __construct(array $keys) { $this->keys = $keys; } /** * Duplicates the given value through the array. * * @param mixed $value The value * * @return array The array */ public function transform($value) { $result = array(); foreach ($this->keys as $key) { $result[$key] = $value; } return $result; } /** * Extracts the duplicated value from an array. * * @param array $array * * @return mixed The value * * @throws TransformationFailedException If the given value is not an array or * if the given array can not be transformed. */ public function reverseTransform($array) { if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } $result = current($array); $emptyKeys = array(); foreach ($this->keys as $key) { if (!empty($array[$key])) { if ($array[$key] !== $result) { throw new TransformationFailedException( 'All values in the array should be the same' ); } } else { $emptyKeys[] = $key; } } if (count($emptyKeys) > 0) { if (count($emptyKeys) == count($this->keys)) { // All keys empty return null; } throw new TransformationFailedException( sprintf('The keys "%s" should not be empty', implode('", "', $emptyKeys) )); } return $result; } } PK]e^  DForm/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer { /** * {@inheritDoc} */ public function transform($dateTime) { if (null === $dateTime) { return ''; } if (!$dateTime instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } if ($this->inputTimezone !== $this->outputTimezone) { $dateTime = clone $dateTime; $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); } return preg_replace('/\+00:00$/', 'Z', $dateTime->format('c')); } /** * {@inheritDoc} */ public function reverseTransform($rfc3339) { if (!is_string($rfc3339)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $rfc3339) { return null; } try { $dateTime = new \DateTime($rfc3339); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } if ($this->outputTimezone !== $dateTime->getTimezone()->getName()) { try { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } } if (preg_match('/(\d{4})-(\d{2})-(\d{2})/', $rfc3339, $matches)) { if (!checkdate($matches[2], $matches[3], $matches[1])) { throw new TransformationFailedException(sprintf( 'The date "%s-%s-%s" is not a valid date.', $matches[1], $matches[2], $matches[3] )); } } return $dateTime; } } PK]]yD D IForm/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a normalized format and a localized money string. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransformer { private $divisor; public function __construct($precision = 2, $grouping = true, $roundingMode = self::ROUND_HALF_UP, $divisor = 1) { if (null === $grouping) { $grouping = true; } if (null === $precision) { $precision = 2; } parent::__construct($precision, $grouping, $roundingMode); if (null === $divisor) { $divisor = 1; } $this->divisor = $divisor; } /** * Transforms a normalized format into a localized money string. * * @param number $value Normalized number * * @return string Localized money string. * * @throws TransformationFailedException If the given value is not numeric or * if the value can not be transformed. */ public function transform($value) { if (null !== $value) { if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } $value /= $this->divisor; } return parent::transform($value); } /** * Transforms a localized money string into a normalized format. * * @param string $value Localized money string * * @return number Normalized number * * @throws TransformationFailedException If the given value is not a string * or if the value can not be transformed. */ public function reverseTransform($value) { $value = parent::reverseTransform($value); if (null !== $value) { $value *= $this->divisor; } return $value; } } PK]'tqk55HForm/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ChoicesToBooleanArrayTransformer implements DataTransformerInterface { private $choiceList; public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } /** * Transforms an array of choices to a format appropriate for the nested * checkboxes/radio buttons. * * The result is an array with the options as keys and true/false as values, * depending on whether a given option is selected. If this field is rendered * as select tag, the value is not modified. * * @param mixed $array An array * * @return mixed An array * * @throws TransformationFailedException If the given value is not an array * or if the choices can not be retrieved. */ public function transform($array) { if (null === $array) { return array(); } if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } try { $values = $this->choiceList->getValues(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } $valueMap = array_flip($this->choiceList->getValuesForChoices($array)); foreach ($values as $i => $value) { $values[$i] = isset($valueMap[$value]); } return $values; } /** * Transforms a checkbox/radio button array to an array of choices. * * The input value is an array with the choices as keys and true/false as * values, depending on whether a given choice is selected. The output * is an array with the selected choices. * * @param mixed $values An array * * @return mixed An array * * @throws TransformationFailedException If the given value is not an array, * if the recuperation of the choices * fails or if some choice can't be * found. */ public function reverseTransform($values) { if (!is_array($values)) { throw new TransformationFailedException('Expected an array.'); } try { $choices = $this->choiceList->getChoices(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } $result = array(); $unknown = array(); foreach ($values as $i => $selected) { if ($selected) { if (isset($choices[$i])) { $result[] = $choices[$i]; } else { $unknown[] = $i; } } } if (count($unknown) > 0) { throw new TransformationFailedException(sprintf('The choices "%s" were not found', implode('", "', $unknown))); } return $result; } } PK]TBForm/Extension/Core/DataTransformer/BooleanToStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a Boolean and a string. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class BooleanToStringTransformer implements DataTransformerInterface { /** * The value emitted upon transform if the input is true * @var string */ private $trueValue; /** * Sets the value emitted upon transform if the input is true. * * @param string $trueValue */ public function __construct($trueValue) { $this->trueValue = $trueValue; } /** * Transforms a Boolean into a string. * * @param Boolean $value Boolean value. * * @return string String value. * * @throws TransformationFailedException If the given value is not a Boolean. */ public function transform($value) { if (null === $value) { return null; } if (!is_bool($value)) { throw new TransformationFailedException('Expected a Boolean.'); } return $value ? $this->trueValue : null; } /** * Transforms a string into a Boolean. * * @param string $value String value. * * @return Boolean Boolean value. * * @throws TransformationFailedException If the given value is not a string. */ public function reverseTransform($value) { if (null === $value) { return false; } if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } return true; } } PK]Lpx&&GForm/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ChoiceToBooleanArrayTransformer implements DataTransformerInterface { private $choiceList; private $placeholderPresent; /** * Constructor. * * @param ChoiceListInterface $choiceList * @param Boolean $placeholderPresent */ public function __construct(ChoiceListInterface $choiceList, $placeholderPresent) { $this->choiceList = $choiceList; $this->placeholderPresent = $placeholderPresent; } /** * Transforms a single choice to a format appropriate for the nested * checkboxes/radio buttons. * * The result is an array with the options as keys and true/false as values, * depending on whether a given option is selected. If this field is rendered * as select tag, the value is not modified. * * @param mixed $choice An array if "multiple" is set to true, a scalar * value otherwise. * * @return mixed An array * * @throws TransformationFailedException If the given value is not scalar or * if the choices can not be retrieved. */ public function transform($choice) { try { $values = $this->choiceList->getValues(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } $valueMap = array_flip($this->choiceList->getValuesForChoices(array($choice))); foreach ($values as $i => $value) { $values[$i] = isset($valueMap[$value]); } if ($this->placeholderPresent) { $values['placeholder'] = 0 === count($valueMap); } return $values; } /** * Transforms a checkbox/radio button array to a single choice. * * The input value is an array with the choices as keys and true/false as * values, depending on whether a given choice is selected. The output * is the selected choice. * * @param array $values An array of values * * @return mixed A scalar value * * @throws TransformationFailedException If the given value is not an array, * if the recuperation of the choices * fails or if some choice can't be * found. */ public function reverseTransform($values) { if (!is_array($values)) { throw new TransformationFailedException('Expected an array.'); } try { $choices = $this->choiceList->getChoices(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } foreach ($values as $i => $selected) { if ($selected) { if (isset($choices[$i])) { return $choices[$i] === '' ? null : $choices[$i]; } elseif ($this->placeholderPresent && 'placeholder' === $i) { return null; } else { throw new TransformationFailedException(sprintf('The choice "%s" does not exist', $i)); } } } return null; } } PK]Ze  BForm/Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a normalized time and a localized time string/array. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToArrayTransformer extends BaseDateTimeTransformer { private $pad; private $fields; /** * Constructor. * * @param string $inputTimezone The input timezone * @param string $outputTimezone The output timezone * @param array $fields The date fields * @param Boolean $pad Whether to use padding * * @throws UnexpectedTypeException if a timezone is not a string */ public function __construct($inputTimezone = null, $outputTimezone = null, array $fields = null, $pad = false) { parent::__construct($inputTimezone, $outputTimezone); if (null === $fields) { $fields = array('year', 'month', 'day', 'hour', 'minute', 'second'); } $this->fields = $fields; $this->pad = (Boolean) $pad; } /** * Transforms a normalized date into a localized date. * * @param \DateTime $dateTime Normalized date. * * @return array Localized date. * * @throws TransformationFailedException If the given value is not an * instance of \DateTime or if the * output timezone is not supported. */ public function transform($dateTime) { if (null === $dateTime) { return array_intersect_key(array( 'year' => '', 'month' => '', 'day' => '', 'hour' => '', 'minute' => '', 'second' => '', ), array_flip($this->fields)); } if (!$dateTime instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } $dateTime = clone $dateTime; if ($this->inputTimezone !== $this->outputTimezone) { try { $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } } $result = array_intersect_key(array( 'year' => $dateTime->format('Y'), 'month' => $dateTime->format('m'), 'day' => $dateTime->format('d'), 'hour' => $dateTime->format('H'), 'minute' => $dateTime->format('i'), 'second' => $dateTime->format('s'), ), array_flip($this->fields)); if (!$this->pad) { foreach ($result as &$entry) { // remove leading zeros $entry = (string) (int) $entry; } } return $result; } /** * Transforms a localized date into a normalized date. * * @param array $value Localized date * * @return \DateTime Normalized date * * @throws TransformationFailedException If the given value is not an array, * if the value could not be transformed * or if the input timezone is not * supported. */ public function reverseTransform($value) { if (null === $value) { return null; } if (!is_array($value)) { throw new TransformationFailedException('Expected an array.'); } if ('' === implode('', $value)) { return null; } $emptyFields = array(); foreach ($this->fields as $field) { if (!isset($value[$field])) { $emptyFields[] = $field; } } if (count($emptyFields) > 0) { throw new TransformationFailedException( sprintf('The fields "%s" should not be empty', implode('", "', $emptyFields) )); } if (isset($value['month']) && !ctype_digit((string) $value['month'])) { throw new TransformationFailedException('This month is invalid'); } if (isset($value['day']) && !ctype_digit((string) $value['day'])) { throw new TransformationFailedException('This day is invalid'); } if (isset($value['year']) && !ctype_digit((string) $value['year'])) { throw new TransformationFailedException('This year is invalid'); } if (!empty($value['month']) && !empty($value['day']) && !empty($value['year']) && false === checkdate($value['month'], $value['day'], $value['year'])) { throw new TransformationFailedException('This is an invalid date'); } if (isset($value['hour']) && !ctype_digit((string) $value['hour'])) { throw new TransformationFailedException('This hour is invalid'); } if (isset($value['minute']) && !ctype_digit((string) $value['minute'])) { throw new TransformationFailedException('This minute is invalid'); } if (isset($value['second']) && !ctype_digit((string) $value['second'])) { throw new TransformationFailedException('This second is invalid'); } try { $dateTime = new \DateTime(sprintf( '%s-%s-%s %s:%s:%s %s', empty($value['year']) ? '1970' : $value['year'], empty($value['month']) ? '1' : $value['month'], empty($value['day']) ? '1' : $value['day'], empty($value['hour']) ? '0' : $value['hour'], empty($value['minute']) ? '0' : $value['minute'], empty($value['second']) ? '0' : $value['second'], $this->outputTimezone )); if ($this->inputTimezone !== $this->outputTimezone) { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $dateTime; } } PK]UdqKForm/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; /** * Transforms between an integer and a localized number with grouping * (each thousand) and comma separators. * * @author Bernhard Schussek */ class IntegerToLocalizedStringTransformer extends NumberToLocalizedStringTransformer { /** * Constructs a transformer. * * @param integer $precision Unused. * @param Boolean $grouping Whether thousands should be grouped. * @param integer $roundingMode One of the ROUND_ constants in this class. */ public function __construct($precision = 0, $grouping = false, $roundingMode = self::ROUND_DOWN) { if (null === $roundingMode) { $roundingMode = self::ROUND_DOWN; } parent::__construct(0, $grouping, $roundingMode); } /** * {@inheritDoc} */ public function reverseTransform($value) { $result = parent::reverseTransform($value); return null !== $result ? (int) $result : null; } } PK]ΎgW CForm/Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a date string and a DateTime object * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToStringTransformer extends BaseDateTimeTransformer { /** * Format used for generating strings * @var string */ private $generateFormat; /** * Format used for parsing strings * * Different than the {@link $generateFormat} because formats for parsing * support additional characters in PHP that are not supported for * generating strings. * * @var string */ private $parseFormat; /** * Whether to parse by appending a pipe "|" to the parse format. * * This only works as of PHP 5.3.7. * * @var Boolean */ private $parseUsingPipe; /** * Transforms a \DateTime instance to a string * * @see \DateTime::format() for supported formats * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * @param string $format The date format * @param Boolean $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format * * @throws UnexpectedTypeException if a timezone is not a string */ public function __construct($inputTimezone = null, $outputTimezone = null, $format = 'Y-m-d H:i:s', $parseUsingPipe = null) { parent::__construct($inputTimezone, $outputTimezone); $this->generateFormat = $this->parseFormat = $format; // The pipe in the parser pattern only works as of PHP 5.3.7 // See http://bugs.php.net/54316 $this->parseUsingPipe = null === $parseUsingPipe ? version_compare(phpversion(), '5.3.7', '>=') : $parseUsingPipe; // See http://php.net/manual/en/datetime.createfromformat.php // The character "|" in the format makes sure that the parts of a date // that are *not* specified in the format are reset to the corresponding // values from 1970-01-01 00:00:00 instead of the current time. // Without "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 12:32:47", // where the time corresponds to the current server time. // With "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 00:00:00", // which is at least deterministic and thus used here. if ($this->parseUsingPipe && false === strpos($this->parseFormat, '|')) { $this->parseFormat .= '|'; } } /** * Transforms a DateTime object into a date string with the configured format * and timezone * * @param \DateTime $value A DateTime object * * @return string A value as produced by PHP's date() function * * @throws TransformationFailedException If the given value is not a \DateTime * instance or if the output timezone * is not supported. */ public function transform($value) { if (null === $value) { return ''; } if (!$value instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } $value = clone $value; try { $value->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $value->format($this->generateFormat); } /** * Transforms a date string in the configured timezone into a DateTime object. * * @param string $value A value as produced by PHP's date() function * * @return \DateTime An instance of \DateTime * * @throws TransformationFailedException If the given value is not a string, * if the date could not be parsed or * if the input timezone is not supported. */ public function reverseTransform($value) { if (empty($value)) { return null; } if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } try { $outputTz = new \DateTimeZone($this->outputTimezone); $dateTime = \DateTime::createFromFormat($this->parseFormat, $value, $outputTz); $lastErrors = \DateTime::getLastErrors(); if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) { throw new TransformationFailedException( implode(', ', array_merge( array_values($lastErrors['warnings']), array_values($lastErrors['errors']) )) ); } // On PHP versions < 5.3.7 we need to emulate the pipe operator // and reset parts not given in the format to their equivalent // of the UNIX base timestamp. if (!$this->parseUsingPipe) { list($year, $month, $day, $hour, $minute, $second) = explode('-', $dateTime->format('Y-m-d-H-i-s')); // Check which of the date parts are present in the pattern preg_match( '/(' . '(?P[djDl])|' . '(?P[FMmn])|' . '(?P[Yy])|' . '(?P[ghGH])|' . '(?Pi)|' . '(?Ps)|' . '(?Pz)|' . '(?PU)|' . '[^djDlFMmnYyghGHiszU]' . ')*/', $this->parseFormat, $matches ); // preg_match() does not guarantee to set all indices, so // set them unless given $matches = array_merge(array( 'day' => false, 'month' => false, 'year' => false, 'hour' => false, 'minute' => false, 'second' => false, 'dayofyear' => false, 'timestamp' => false, ), $matches); // Reset all parts that don't exist in the format to the // corresponding part of the UNIX base timestamp if (!$matches['timestamp']) { if (!$matches['dayofyear']) { if (!$matches['day']) { $day = 1; } if (!$matches['month']) { $month = 1; } } if (!$matches['year']) { $year = 1970; } if (!$matches['hour']) { $hour = 0; } if (!$matches['minute']) { $minute = 0; } if (!$matches['second']) { $second = 0; } $dateTime->setDate($year, $month, $day); $dateTime->setTime($hour, $minute, $second); } } if ($this->inputTimezone !== $this->outputTimezone) { $dateTime->setTimeZone(new \DateTimeZone($this->inputTimezone)); } } catch (TransformationFailedException $e) { throw $e; } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $dateTime; } } PK]O###JForm/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a number type and a localized number with grouping * (each thousand) and comma separators. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class NumberToLocalizedStringTransformer implements DataTransformerInterface { /** * Rounds a number towards positive infinity. * * Rounds 1.4 to 2 and -1.4 to -1. */ const ROUND_CEILING = \NumberFormatter::ROUND_CEILING; /** * Rounds a number towards negative infinity. * * Rounds 1.4 to 1 and -1.4 to -2. */ const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR; /** * Rounds a number away from zero. * * Rounds 1.4 to 2 and -1.4 to -2. */ const ROUND_UP = \NumberFormatter::ROUND_UP; /** * Rounds a number towards zero. * * Rounds 1.4 to 1 and -1.4 to -1. */ const ROUND_DOWN = \NumberFormatter::ROUND_DOWN; /** * Rounds to the nearest number and halves to the next even number. * * Rounds 2.5, 1.6 and 1.5 to 2 and 1.4 to 1. */ const ROUND_HALF_EVEN = \NumberFormatter::ROUND_HALFEVEN; /** * Rounds to the nearest number and halves away from zero. * * Rounds 2.5 to 3, 1.6 and 1.5 to 2 and 1.4 to 1. */ const ROUND_HALF_UP = \NumberFormatter::ROUND_HALFUP; /** * Rounds to the nearest number and halves towards zero. * * Rounds 2.5 and 1.6 to 2, 1.5 and 1.4 to 1. */ const ROUND_HALF_DOWN = \NumberFormatter::ROUND_HALFDOWN; /** * Alias for {@link self::ROUND_HALF_EVEN}. * * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. */ const ROUND_HALFEVEN = self::ROUND_HALF_EVEN; /** * Alias for {@link self::ROUND_HALF_UP}. * * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. */ const ROUND_HALFUP = self::ROUND_HALF_UP; /** * Alias for {@link self::ROUND_HALF_DOWN}. * * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. */ const ROUND_HALFDOWN = self::ROUND_HALF_DOWN; protected $precision; protected $grouping; protected $roundingMode; public function __construct($precision = null, $grouping = false, $roundingMode = self::ROUND_HALF_UP) { if (null === $grouping) { $grouping = false; } if (null === $roundingMode) { $roundingMode = self::ROUND_HALF_UP; } $this->precision = $precision; $this->grouping = $grouping; $this->roundingMode = $roundingMode; } /** * Transforms a number type into localized number. * * @param integer|float $value Number value. * * @return string Localized value. * * @throws TransformationFailedException If the given value is not numeric * or if the value can not be transformed. */ public function transform($value) { if (null === $value) { return ''; } if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } $formatter = $this->getNumberFormatter(); $value = $formatter->format($value); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } // Convert fixed spaces to normal ones $value = str_replace("\xc2\xa0", ' ', $value); return $value; } /** * Transforms a localized number into an integer or float * * @param string $value The localized value * * @return integer|float The numeric value * * @throws TransformationFailedException If the given value is not a string * or if the value can not be transformed. */ public function reverseTransform($value) { if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $value) { return null; } if ('NaN' === $value) { throw new TransformationFailedException('"NaN" is not a valid number'); } $position = 0; $formatter = $this->getNumberFormatter(); $groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL); $decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); if ('.' !== $decSep && (!$this->grouping || '.' !== $groupSep)) { $value = str_replace('.', $decSep, $value); } if (',' !== $decSep && (!$this->grouping || ',' !== $groupSep)) { $value = str_replace(',', $decSep, $value); } $result = $formatter->parse($value, \NumberFormatter::TYPE_DOUBLE, $position); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } if ($result >= PHP_INT_MAX || $result <= -PHP_INT_MAX) { throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like'); } if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value)) { $strlen = function ($string) use ($encoding) { return mb_strlen($string, $encoding); }; $substr = function ($string, $offset, $length) use ($encoding) { return mb_substr($string, $offset, $length, $encoding); }; } else { $strlen = 'strlen'; $substr = 'substr'; } $length = $strlen($value); // After parsing, position holds the index of the character where the // parsing stopped if ($position < $length) { // Check if there are unrecognized characters at the end of the // number (excluding whitespace characters) $remainder = trim($substr($value, $position, $length), " \t\n\r\0\x0b\xc2\xa0"); if ('' !== $remainder) { throw new TransformationFailedException( sprintf('The number contains unrecognized characters: "%s"', $remainder) ); } } // NumberFormatter::parse() does not round return $this->round($result); } /** * Returns a preconfigured \NumberFormatter instance * * @return \NumberFormatter */ protected function getNumberFormatter() { $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL); if (null !== $this->precision) { $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->precision); $formatter->setAttribute(\NumberFormatter::ROUNDING_MODE, $this->roundingMode); } $formatter->setAttribute(\NumberFormatter::GROUPING_USED, $this->grouping); return $formatter; } /** * Rounds a number according to the configured precision and rounding mode. * * @param integer|float $number A number. * * @return integer|float The rounded number. */ private function round($number) { if (null !== $this->precision && null !== $this->roundingMode) { // shift number to maintain the correct precision during rounding $roundingCoef = pow(10, $this->precision); $number *= $roundingCoef; switch ($this->roundingMode) { case self::ROUND_CEILING: $number = ceil($number); break; case self::ROUND_FLOOR: $number = floor($number); break; case self::ROUND_UP: $number = $number > 0 ? ceil($number) : floor($number); break; case self::ROUND_DOWN: $number = $number > 0 ? floor($number) : ceil($number); break; case self::ROUND_HALF_EVEN: $number = round($number, 0, PHP_ROUND_HALF_EVEN); break; case self::ROUND_HALF_UP: $number = round($number, 0, PHP_ROUND_HALF_UP); break; case self::ROUND_HALF_DOWN: $number = round($number, 0, PHP_ROUND_HALF_DOWN); break; } $number /= $roundingCoef; } return $number; } } PK]"h@Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * @author Bernhard Schussek */ class ChoiceToValueTransformer implements DataTransformerInterface { private $choiceList; /** * Constructor. * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } public function transform($choice) { return (string) current($this->choiceList->getValuesForChoices(array($choice))); } public function reverseTransform($value) { if (null !== $value && !is_scalar($value)) { throw new TransformationFailedException('Expected a scalar.'); } // These are now valid ChoiceList values, so we can return null // right away if ('' === $value || null === $value) { return null; } $choices = $this->choiceList->getChoicesForValues(array($value)); if (1 !== count($choices)) { throw new TransformationFailedException(sprintf('The choice "%s" does not exist or is not unique', $value)); } $choice = current($choices); return '' === $choice ? null : $choice; } } PK]Þ FForm/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a timestamp and a DateTime object * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer { /** * Transforms a DateTime object into a timestamp in the configured timezone. * * @param \DateTime $value A \DateTime object * * @return integer A timestamp * * @throws TransformationFailedException If the given value is not an instance * of \DateTime or if the output * timezone is not supported. */ public function transform($value) { if (null === $value) { return null; } if (!$value instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } $value = clone $value; try { $value->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return (int) $value->format('U'); } /** * Transforms a timestamp in the configured timezone into a DateTime object * * @param string $value A timestamp * * @return \DateTime A \DateTime object * * @throws TransformationFailedException If the given value is not a timestamp * or if the given timestamp is invalid. */ public function reverseTransform($value) { if (null === $value) { return null; } if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } try { $dateTime = new \DateTime(); $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); $dateTime->setTimestamp($value); if ($this->inputTimezone !== $this->outputTimezone) { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $dateTime; } } PK]'ç??-Form/Extension/Core/ChoiceList/ChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Extension\Core\View\ChoiceView; /** * A choice list for choices of arbitrary data types. * * Choices and labels are passed in two arrays. The indices of the choices * and the labels should match. Choices may also be given as hierarchy of * unlimited depth by creating nested arrays. The title of the sub-hierarchy * can be stored in the array key pointing to the nested array. The topmost * level of the hierarchy may also be a \Traversable. * * * $choices = array(true, false); * $labels = array('Agree', 'Disagree'); * $choiceList = new ChoiceList($choices, $labels); * * * @author Bernhard Schussek */ class ChoiceList implements ChoiceListInterface { /** * The choices with their indices as keys. * * @var array */ private $choices = array(); /** * The choice values with the indices of the matching choices as keys. * * @var array */ private $values = array(); /** * The preferred view objects as hierarchy containing also the choice groups * with the indices of the matching choices as bottom-level keys. * * @var array */ private $preferredViews = array(); /** * The non-preferred view objects as hierarchy containing also the choice * groups with the indices of the matching choices as bottom-level keys. * * @var array */ private $remainingViews = array(); /** * Creates a new choice list. * * @param array|\Traversable $choices The array of choices. Choices may also be given * as hierarchy of unlimited depth. Hierarchies are * created by creating nested arrays. The title of * the sub-hierarchy can be stored in the array * key pointing to the nested array. The topmost * level of the hierarchy may also be a \Traversable. * @param array $labels The array of labels. The structure of this array * should match the structure of $choices. * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. * * @throws UnexpectedTypeException If the choices are not an array or \Traversable. */ public function __construct($choices, array $labels, array $preferredChoices = array()) { if (!is_array($choices) && !$choices instanceof \Traversable) { throw new UnexpectedTypeException($choices, 'array or \Traversable'); } $this->initialize($choices, $labels, $preferredChoices); } /** * Initializes the list with choices. * * Safe to be called multiple times. The list is cleared on every call. * * @param array|\Traversable $choices The choices to write into the list. * @param array $labels The labels belonging to the choices. * @param array $preferredChoices The choices to display with priority. */ protected function initialize($choices, array $labels, array $preferredChoices) { $this->choices = array(); $this->values = array(); $this->preferredViews = array(); $this->remainingViews = array(); $this->addChoices( $this->preferredViews, $this->remainingViews, $choices, $labels, $preferredChoices ); } /** * {@inheritdoc} */ public function getChoices() { return $this->choices; } /** * {@inheritdoc} */ public function getValues() { return $this->values; } /** * {@inheritdoc} */ public function getPreferredViews() { return $this->preferredViews; } /** * {@inheritdoc} */ public function getRemainingViews() { return $this->remainingViews; } /** * {@inheritdoc} */ public function getChoicesForValues(array $values) { $values = $this->fixValues($values); $choices = array(); foreach ($values as $i => $givenValue) { foreach ($this->values as $j => $value) { if ($value === $givenValue) { $choices[$i] = $this->choices[$j]; unset($values[$i]); if (0 === count($values)) { break 2; } } } } return $choices; } /** * {@inheritdoc} */ public function getValuesForChoices(array $choices) { $choices = $this->fixChoices($choices); $values = array(); foreach ($choices as $i => $givenChoice) { foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { $values[$i] = $this->values[$j]; unset($choices[$i]); if (0 === count($choices)) { break 2; } } } } return $values; } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices) { $choices = $this->fixChoices($choices); $indices = array(); foreach ($choices as $i => $givenChoice) { foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { $indices[$i] = $j; unset($choices[$i]); if (0 === count($choices)) { break 2; } } } } return $indices; } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values) { $values = $this->fixValues($values); $indices = array(); foreach ($values as $i => $givenValue) { foreach ($this->values as $j => $value) { if ($value === $givenValue) { $indices[$i] = $j; unset($values[$i]); if (0 === count($values)) { break 2; } } } } return $indices; } /** * Recursively adds the given choices to the list. * * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param array|\Traversable $choices The list of choices. * @param array $labels The labels corresponding to the choices. * @param array $preferredChoices The preferred choices. * * @throws InvalidArgumentException If the structures of the choices and labels array do not match. * @throws InvalidConfigurationException If no valid value or index could be created for a choice. */ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices) { // Add choices to the nested buckets foreach ($choices as $group => $choice) { if (!array_key_exists($group, $labels)) { throw new InvalidArgumentException('The structures of the choices and labels array do not match.'); } if (is_array($choice)) { // Don't do the work if the array is empty if (count($choice) > 0) { $this->addChoiceGroup( $group, $bucketForPreferred, $bucketForRemaining, $choice, $labels[$group], $preferredChoices ); } } else { $this->addChoice( $bucketForPreferred, $bucketForRemaining, $choice, $labels[$group], $preferredChoices ); } } } /** * Recursively adds a choice group. * * @param string $group The name of the group. * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param array $choices The list of choices in the group. * @param array $labels The labels corresponding to the choices in the group. * @param array $preferredChoices The preferred choices. * * @throws InvalidConfigurationException If no valid value or index could be created for a choice. */ protected function addChoiceGroup($group, array &$bucketForPreferred, array &$bucketForRemaining, array $choices, array $labels, array $preferredChoices) { // If this is a choice group, create a new level in the choice // key hierarchy $bucketForPreferred[$group] = array(); $bucketForRemaining[$group] = array(); $this->addChoices( $bucketForPreferred[$group], $bucketForRemaining[$group], $choices, $labels, $preferredChoices ); // Remove child levels if empty if (empty($bucketForPreferred[$group])) { unset($bucketForPreferred[$group]); } if (empty($bucketForRemaining[$group])) { unset($bucketForRemaining[$group]); } } /** * Adds a new choice. * * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param mixed $choice The choice to add. * @param string $label The label for the choice. * @param array $preferredChoices The preferred choices. * * @throws InvalidConfigurationException If no valid value or index could be created. */ protected function addChoice(array &$bucketForPreferred, array &$bucketForRemaining, $choice, $label, array $preferredChoices) { $index = $this->createIndex($choice); if ('' === $index || null === $index || !FormConfigBuilder::isValidName((string) $index)) { throw new InvalidConfigurationException(sprintf('The index "%s" created by the choice list is invalid. It should be a valid, non-empty Form name.', $index)); } $value = $this->createValue($choice); if (!is_string($value)) { throw new InvalidConfigurationException(sprintf('The value created by the choice list is of type "%s", but should be a string.', gettype($value))); } $view = new ChoiceView($choice, $value, $label); $this->choices[$index] = $this->fixChoice($choice); $this->values[$index] = $value; if ($this->isPreferred($choice, $preferredChoices)) { $bucketForPreferred[$index] = $view; } else { $bucketForRemaining[$index] = $view; } } /** * Returns whether the given choice should be preferred judging by the * given array of preferred choices. * * Extension point to optimize performance by changing the structure of the * $preferredChoices array. * * @param mixed $choice The choice to test. * @param array $preferredChoices An array of preferred choices. * * @return Boolean Whether the choice is preferred. */ protected function isPreferred($choice, array $preferredChoices) { return false !== array_search($choice, $preferredChoices, true); } /** * Creates a new unique index for this choice. * * Extension point to change the indexing strategy. * * @param mixed $choice The choice to create an index for * * @return integer|string A unique index containing only ASCII letters, * digits and underscores. */ protected function createIndex($choice) { return count($this->choices); } /** * Creates a new unique value for this choice. * * By default, an integer is generated since it cannot be guaranteed that * all values in the list are convertible to (unique) strings. Subclasses * can override this behaviour if they can guarantee this property. * * @param mixed $choice The choice to create a value for * * @return string A unique string. */ protected function createValue($choice) { return (string) count($this->values); } /** * Fixes the data type of the given choice value to avoid comparison * problems. * * @param mixed $value The choice value. * * @return string The value as string. */ protected function fixValue($value) { return (string) $value; } /** * Fixes the data types of the given choice values to avoid comparison * problems. * * @param array $values The choice values. * * @return array The values as strings. */ protected function fixValues(array $values) { foreach ($values as $i => $value) { $values[$i] = $this->fixValue($value); } return $values; } /** * Fixes the data type of the given choice index to avoid comparison * problems. * * @param mixed $index The choice index. * * @return integer|string The index as PHP array key. */ protected function fixIndex($index) { if (is_bool($index) || (string) (int) $index === (string) $index) { return (int) $index; } return (string) $index; } /** * Fixes the data types of the given choice indices to avoid comparison * problems. * * @param array $indices The choice indices. * * @return array The indices as strings. */ protected function fixIndices(array $indices) { foreach ($indices as $i => $index) { $indices[$i] = $this->fixIndex($index); } return $indices; } /** * Fixes the data type of the given choice to avoid comparison problems. * * Extension point. In this implementation, choices are guaranteed to * always maintain their type and thus can be typesafely compared. * * @param mixed $choice The choice * * @return mixed The fixed choice */ protected function fixChoice($choice) { return $choice; } /** * Fixes the data type of the given choices to avoid comparison problems. * * @param array $choices The choices. * * @return array The fixed choices. * * @see fixChoice */ protected function fixChoices(array $choices) { return $choices; } } PK] ##3Form/Extension/Core/ChoiceList/ObjectChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; use Symfony\Component\Form\Exception\StringCastException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; /** * A choice list for object choices. * * Supports generation of choice labels, choice groups and choice values * by calling getters of the object (or associated objects). * * * $choices = array($user1, $user2); * * // call getName() to determine the choice labels * $choiceList = new ObjectChoiceList($choices, 'name'); * * * @author Bernhard Schussek */ class ObjectChoiceList extends ChoiceList { /** * @var PropertyAccessorInterface */ private $propertyAccessor; /** * The property path used to obtain the choice label. * * @var PropertyPath */ private $labelPath; /** * The property path used for object grouping. * * @var PropertyPath */ private $groupPath; /** * The property path used to obtain the choice value. * * @var PropertyPath */ private $valuePath; /** * Creates a new object choice list. * * @param array|\Traversable $choices The array of choices. Choices may also be given * as hierarchy of unlimited depth by creating nested * arrays. The title of the sub-hierarchy can be * stored in the array key pointing to the nested * array. The topmost level of the hierarchy may also * be a \Traversable. * @param string $labelPath A property path pointing to the property used * for the choice labels. The value is obtained * by calling the getter on the object. If the * path is NULL, the object's __toString() method * is used instead. * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. * @param string $groupPath A property path pointing to the property used * to group the choices. Only allowed if * the choices are given as flat array. * @param string $valuePath A property path pointing to the property used * for the choice values. If not given, integers * are generated instead. * @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths. */ public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null, PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); $this->labelPath = null !== $labelPath ? new PropertyPath($labelPath) : null; $this->groupPath = null !== $groupPath ? new PropertyPath($groupPath) : null; $this->valuePath = null !== $valuePath ? new PropertyPath($valuePath) : null; parent::__construct($choices, array(), $preferredChoices); } /** * Initializes the list with choices. * * Safe to be called multiple times. The list is cleared on every call. * * @param array|\Traversable $choices The choices to write into the list. * @param array $labels Ignored. * @param array $preferredChoices The choices to display with priority. * * @throws InvalidArgumentException When passing a hierarchy of choices and using * the "groupPath" option at the same time. */ protected function initialize($choices, array $labels, array $preferredChoices) { if (null !== $this->groupPath) { $groupedChoices = array(); foreach ($choices as $i => $choice) { if (is_array($choice)) { throw new InvalidArgumentException('You should pass a plain object array (without groups) when using the "groupPath" option.'); } try { $group = $this->propertyAccessor->getValue($choice, $this->groupPath); } catch (NoSuchPropertyException $e) { // Don't group items whose group property does not exist // see https://github.com/symfony/symfony/commit/d9b7abb7c7a0f28e0ce970afc5e305dce5dccddf $group = null; } if (null === $group) { $groupedChoices[$i] = $choice; } else { $groupName = (string) $group; if (!isset($groupedChoices[$groupName])) { $groupedChoices[$groupName] = array(); } $groupedChoices[$groupName][$i] = $choice; } } $choices = $groupedChoices; } $labels = array(); $this->extractLabels($choices, $labels); parent::initialize($choices, $labels, $preferredChoices); } /** * Creates a new unique value for this choice. * * If a property path for the value was given at object creation, * the getter behind that path is now called to obtain a new value. * Otherwise a new integer is generated. * * @param mixed $choice The choice to create a value for * * @return integer|string A unique value without character limitations. */ protected function createValue($choice) { if ($this->valuePath) { return (string) $this->propertyAccessor->getValue($choice, $this->valuePath); } return parent::createValue($choice); } private function extractLabels($choices, array &$labels) { foreach ($choices as $i => $choice) { if (is_array($choice)) { $labels[$i] = array(); $this->extractLabels($choice, $labels[$i]); } elseif ($this->labelPath) { $labels[$i] = $this->propertyAccessor->getValue($choice, $this->labelPath); } elseif (method_exists($choice, '__toString')) { $labels[$i] = (string) $choice; } else { throw new StringCastException(sprintf('A "__toString()" method was not found on the objects of type "%s" passed to the choice field. To read a custom getter instead, set the argument $labelPath to the desired property path.', get_class($choice))); } } } } PK]В4 4 1Form/Extension/Core/ChoiceList/LazyChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * A choice list that is loaded lazily * * This list loads itself as soon as any of the getters is accessed for the * first time. You should implement loadChoiceList() in your child classes, * which should return a ChoiceListInterface instance. * * @author Bernhard Schussek */ abstract class LazyChoiceList implements ChoiceListInterface { /** * The loaded choice list * * @var ChoiceListInterface */ private $choiceList; /** * {@inheritdoc} */ public function getChoices() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getChoices(); } /** * {@inheritdoc} */ public function getValues() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getValues(); } /** * {@inheritdoc} */ public function getPreferredViews() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getPreferredViews(); } /** * {@inheritdoc} */ public function getRemainingViews() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getRemainingViews(); } /** * {@inheritdoc} */ public function getChoicesForValues(array $values) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getChoicesForValues($values); } /** * {@inheritdoc} */ public function getValuesForChoices(array $choices) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getValuesForChoices($choices); } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getIndicesForChoices($choices); } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getIndicesForValues($values); } /** * Loads the choice list * * Should be implemented by child classes. * * @return ChoiceListInterface The loaded choice list */ abstract protected function loadChoiceList(); private function load() { $choiceList = $this->loadChoiceList(); if (!$choiceList instanceof ChoiceListInterface) { throw new InvalidArgumentException(sprintf('loadChoiceList() should return a ChoiceListInterface instance. Got %s', gettype($choiceList))); } $this->choiceList = $choiceList; } } PK]jю3Form/Extension/Core/ChoiceList/SimpleChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; /** * A choice list for choices of type string or integer. * * Choices and their associated labels can be passed in a single array. Since * choices are passed as array keys, only strings or integer choices are * allowed. Choices may also be given as hierarchy of unlimited depth by * creating nested arrays. The title of the sub-hierarchy can be stored in the * array key pointing to the nested array. * * * $choiceList = new SimpleChoiceList(array( * 'creditcard' => 'Credit card payment', * 'cash' => 'Cash payment', * )); * * * @author Bernhard Schussek */ class SimpleChoiceList extends ChoiceList { /** * Creates a new simple choice list. * * @param array $choices The array of choices with the choices as keys and * the labels as values. Choices may also be given * as hierarchy of unlimited depth by creating nested * arrays. The title of the sub-hierarchy is stored * in the array key pointing to the nested array. * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. */ public function __construct(array $choices, array $preferredChoices = array()) { // Flip preferred choices to speed up lookup parent::__construct($choices, $choices, array_flip($preferredChoices)); } /** * {@inheritdoc} */ public function getChoicesForValues(array $values) { $values = $this->fixValues($values); // The values are identical to the choices, so we can just return them // to improve performance a little bit return $this->fixChoices(array_intersect($values, $this->getValues())); } /** * {@inheritdoc} */ public function getValuesForChoices(array $choices) { $choices = $this->fixChoices($choices); // The choices are identical to the values, so we can just return them // to improve performance a little bit return $this->fixValues(array_intersect($choices, $this->getValues())); } /** * Recursively adds the given choices to the list. * * Takes care of splitting the single $choices array passed in the * constructor into choices and labels. * * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param array|\Traversable $choices The list of choices. * @param array $labels Ignored. * @param array $preferredChoices The preferred choices. */ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices) { // Add choices to the nested buckets foreach ($choices as $choice => $label) { if (is_array($label)) { // Don't do the work if the array is empty if (count($label) > 0) { $this->addChoiceGroup( $choice, $bucketForPreferred, $bucketForRemaining, $label, $label, $preferredChoices ); } } else { $this->addChoice( $bucketForPreferred, $bucketForRemaining, $choice, $label, $preferredChoices ); } } } /** * Returns whether the given choice should be preferred judging by the * given array of preferred choices. * * Optimized for performance by treating the preferred choices as array * where choices are stored in the keys. * * @param mixed $choice The choice to test. * @param array $preferredChoices An array of preferred choices. * * @return Boolean Whether the choice is preferred. */ protected function isPreferred($choice, array $preferredChoices) { // Optimize performance over the default implementation return isset($preferredChoices[$choice]); } /** * Converts the choice to a valid PHP array key. * * @param mixed $choice The choice * * @return string|integer A valid PHP array key */ protected function fixChoice($choice) { return $this->fixIndex($choice); } /** * {@inheritdoc} */ protected function fixChoices(array $choices) { return $this->fixIndices($choices); } /** * {@inheritdoc} */ protected function createValue($choice) { // Choices are guaranteed to be unique and scalar, so we can simply // convert them to strings return (string) $choice; } } PK]l_R(6Form/Extension/Core/ChoiceList/ChoiceListInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; /** * Contains choices that can be selected in a form field. * * Each choice has three different properties: * * - Choice: The choice that should be returned to the application by the * choice field. Can be any scalar value or an object, but no * array. * - Label: A text representing the choice that is displayed to the user. * - Value: A uniquely identifying value that can contain arbitrary * characters, but no arrays or objects. This value is displayed * in the HTML "value" attribute. * * @author Bernhard Schussek */ interface ChoiceListInterface { /** * Returns the list of choices * * @return array The choices with their indices as keys */ public function getChoices(); /** * Returns the values for the choices * * @return array The values with the corresponding choice indices as keys */ public function getValues(); /** * Returns the choice views of the preferred choices as nested array with * the choice groups as top-level keys. * * Example: * * * array( * 'Group 1' => array( * 10 => ChoiceView object, * 20 => ChoiceView object, * ), * 'Group 2' => array( * 30 => ChoiceView object, * ), * ) * * * @return array A nested array containing the views with the corresponding * choice indices as keys on the lowest levels and the choice * group names in the keys of the higher levels */ public function getPreferredViews(); /** * Returns the choice views of the choices that are not preferred as nested * array with the choice groups as top-level keys. * * Example: * * * array( * 'Group 1' => array( * 10 => ChoiceView object, * 20 => ChoiceView object, * ), * 'Group 2' => array( * 30 => ChoiceView object, * ), * ) * * * @return array A nested array containing the views with the corresponding * choice indices as keys on the lowest levels and the choice * group names in the keys of the higher levels * * @see getPreferredValues */ public function getRemainingViews(); /** * Returns the choices corresponding to the given values. * * The choices can have any data type. * * The choices must be returned with the same keys and in the same order * as the corresponding values in the given array. * * @param array $values An array of choice values. Not existing values in * this array are ignored * * @return array An array of choices with ascending, 0-based numeric keys */ public function getChoicesForValues(array $values); /** * Returns the values corresponding to the given choices. * * The values must be strings. * * The values must be returned with the same keys and in the same order * as the corresponding choices in the given array. * * @param array $choices An array of choices. Not existing choices in this * array are ignored * * @return array An array of choice values with ascending, 0-based numeric * keys */ public function getValuesForChoices(array $choices); /** * Returns the indices corresponding to the given choices. * * The indices must be positive integers or strings accepted by * {@link FormConfigBuilder::validateName()}. * * The index "placeholder" is internally reserved. * * The indices must be returned with the same keys and in the same order * as the corresponding choices in the given array. * * @param array $choices An array of choices. Not existing choices in this * array are ignored * * @return array An array of indices with ascending, 0-based numeric keys * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices); /** * Returns the indices corresponding to the given values. * * The indices must be positive integers or strings accepted by * {@link FormConfigBuilder::validateName()}. * * The index "placeholder" is internally reserved. * * The indices must be returned with the same keys and in the same order * as the corresponding values in the given array. * * @param array $values An array of choice values. Not existing values in * this array are ignored * * @return array An array of indices with ascending, 0-based numeric keys * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values); } PK]>Q?<Form/Extension/Core/EventListener/FixUrlProtocolListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Adds a protocol to a URL if it doesn't already have one. * * @author Bernhard Schussek */ class FixUrlProtocolListener implements EventSubscriberInterface { private $defaultProtocol; public function __construct($defaultProtocol = 'http') { $this->defaultProtocol = $defaultProtocol; } public function onSubmit(FormEvent $event) { $data = $event->getData(); if ($this->defaultProtocol && $data && !preg_match('~^\w+://~', $data)) { $event->setData($this->defaultProtocol.'://'.$data); } } /** * Alias of {@link onSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link onSubmit()} instead. */ public function onBind(FormEvent $event) { $this->onSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::SUBMIT => 'onSubmit'); } } PK]?D;Form/Extension/Core/EventListener/FixRadioInputListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * Takes care of converting the input from a single radio button * to an array. * * @author Bernhard Schussek */ class FixRadioInputListener implements EventSubscriberInterface { private $choiceList; private $placeholderPresent; /** * Constructor. * * @param ChoiceListInterface $choiceList * @param Boolean $placeholderPresent */ public function __construct(ChoiceListInterface $choiceList, $placeholderPresent) { $this->choiceList = $choiceList; $this->placeholderPresent = $placeholderPresent; } public function preSubmit(FormEvent $event) { $data = $event->getData(); // Since expanded choice fields are completely loaded anyway, we // can just as well get the values again without losing performance. $existingValues = $this->choiceList->getValues(); if (false !== ($index = array_search($data, $existingValues, true))) { $data = array($index => $data); } elseif ('' === $data || null === $data) { // Empty values are always accepted. $data = $this->placeholderPresent ? array('placeholder' => '') : array(); } // Else leave the data unchanged to provoke an error during submission $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } PK]õe=Form/Extension/Core/EventListener/MergeCollectionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ class MergeCollectionListener implements EventSubscriberInterface { /** * Whether elements may be added to the collection * @var Boolean */ private $allowAdd; /** * Whether elements may be removed from the collection * @var Boolean */ private $allowDelete; /** * Creates a new listener. * * @param Boolean $allowAdd Whether values might be added to the * collection. * @param Boolean $allowDelete Whether values might be removed from the * collection. */ public function __construct($allowAdd = false, $allowDelete = false) { $this->allowAdd = $allowAdd; $this->allowDelete = $allowDelete; } public static function getSubscribedEvents() { return array( FormEvents::SUBMIT => 'onSubmit', ); } public function onSubmit(FormEvent $event) { $dataToMergeInto = $event->getForm()->getNormData(); $data = $event->getData(); if (null === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } if (null !== $dataToMergeInto && !is_array($dataToMergeInto) && !($dataToMergeInto instanceof \Traversable && $dataToMergeInto instanceof \ArrayAccess)) { throw new UnexpectedTypeException($dataToMergeInto, 'array or (\Traversable and \ArrayAccess)'); } // If we are not allowed to change anything, return immediately if ((!$this->allowAdd && !$this->allowDelete) || $data === $dataToMergeInto) { $event->setData($dataToMergeInto); return; } if (!$dataToMergeInto) { // No original data was set. Set it if allowed if ($this->allowAdd) { $dataToMergeInto = $data; } } else { // Calculate delta $itemsToAdd = is_object($data) ? clone $data : $data; $itemsToDelete = array(); foreach ($dataToMergeInto as $beforeKey => $beforeItem) { foreach ($data as $afterKey => $afterItem) { if ($afterItem === $beforeItem) { // Item found, next original item unset($itemsToAdd[$afterKey]); continue 2; } } // Item not found, remember for deletion $itemsToDelete[] = $beforeKey; } // Remove deleted items before adding to free keys that are to be // replaced if ($this->allowDelete) { foreach ($itemsToDelete as $key) { unset($dataToMergeInto[$key]); } } // Add remaining items if ($this->allowAdd) { foreach ($itemsToAdd as $key => $item) { if (!isset($dataToMergeInto[$key])) { $dataToMergeInto[$key] = $item; } else { $dataToMergeInto[] = $item; } } } } $event->setData($dataToMergeInto); } /** * Alias of {@link onSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link onSubmit()} instead. */ public function onBind(FormEvent $event) { $this->onSubmit($event); } } PK]:AA2Form/Extension/Core/EventListener/TrimListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Trims string data * * @author Bernhard Schussek */ class TrimListener implements EventSubscriberInterface { public function preSubmit(FormEvent $event) { $data = $event->getData(); if (!is_string($data)) { return; } if (null !== $result = @preg_replace('/^[\pZ\p{Cc}]+|[\pZ\p{Cc}]+$/u', '', $data)) { $event->setData($result); } else { $event->setData(trim($data)); } } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } PK]b >Form/Extension/Core/EventListener/FixCheckboxInputListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * Takes care of converting the input from a list of checkboxes to a correctly * indexed array. * * @author Bernhard Schussek */ class FixCheckboxInputListener implements EventSubscriberInterface { private $choiceList; /** * Constructor. * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } public function preSubmit(FormEvent $event) { $data = $event->getData(); if (is_array($data)) { // Flip the submitted values for faster lookup // It's better to flip this array than $existingValues because // $submittedValues is generally smaller. $submittedValues = array_flip($data); // Since expanded choice fields are completely loaded anyway, we // can just as well get the values again without losing performance. $existingValues = $this->choiceList->getValues(); // Clear the data array and fill it with correct indices $data = array(); foreach ($existingValues as $index => $value) { if (isset($submittedValues[$value])) { // Value was submitted $data[$index] = $value; unset($submittedValues[$value]); } } if (count($submittedValues) > 0) { throw new TransformationFailedException(sprintf( 'The following choices were not found: "%s"', implode('", "', array_keys($submittedValues)) )); } } elseif ('' === $data || null === $data) { // Empty values are always accepted. $data = array(); } // Else leave the data unchanged to provoke an error during submission $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } PK]\//8Form/Extension/Core/EventListener/ResizeFormListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Resize a collection form element based on the data sent from the client. * * @author Bernhard Schussek */ class ResizeFormListener implements EventSubscriberInterface { /** * @var string */ protected $type; /** * @var array */ protected $options; /** * Whether children could be added to the group * @var Boolean */ protected $allowAdd; /** * Whether children could be removed from the group * @var Boolean */ protected $allowDelete; public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false) { $this->type = $type; $this->allowAdd = $allowAdd; $this->allowDelete = $allowDelete; $this->options = $options; } public static function getSubscribedEvents() { return array( FormEvents::PRE_SET_DATA => 'preSetData', FormEvents::PRE_SUBMIT => 'preSubmit', // (MergeCollectionListener, MergeDoctrineCollectionListener) FormEvents::SUBMIT => array('onSubmit', 50), ); } public function preSetData(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if (null === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } // First remove all rows foreach ($form as $name => $child) { $form->remove($name); } // Then add all rows again in the correct order foreach ($data as $name => $value) { $form->add($name, $this->type, array_replace(array( 'property_path' => '['.$name.']', ), $this->options)); } } public function preSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if (null === $data || '' === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } // Remove all empty rows if ($this->allowDelete) { foreach ($form as $name => $child) { if (!isset($data[$name])) { $form->remove($name); } } } // Add all additional rows if ($this->allowAdd) { foreach ($data as $name => $value) { if (!$form->has($name)) { $form->add($name, $this->type, array_replace(array( 'property_path' => '['.$name.']', ), $this->options)); } } } } public function onSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if (null === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } // The data mapper only adds, but does not remove items, so do this // here if ($this->allowDelete) { $toDelete = array(); foreach ($data as $name => $child) { if (!$form->has($name)) { $toDelete[] = $name; } } foreach ($toDelete as $name) { unset($data[$name]); } } $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } /** * Alias of {@link onSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link onSubmit()} instead. */ public function onBind(FormEvent $event) { $this->onSubmit($event); } } PK]CW%Form/Extension/Core/CoreExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\PropertyAccess\PropertyAccess; /** * Represents the main form extension, which loads the core functionality. * * @author Bernhard Schussek */ class CoreExtension extends AbstractExtension { protected function loadTypes() { return array( new Type\FormType(PropertyAccess::createPropertyAccessor()), new Type\BirthdayType(), new Type\CheckboxType(), new Type\ChoiceType(), new Type\CollectionType(), new Type\CountryType(), new Type\DateType(), new Type\DateTimeType(), new Type\EmailType(), new Type\HiddenType(), new Type\IntegerType(), new Type\LanguageType(), new Type\LocaleType(), new Type\MoneyType(), new Type\NumberType(), new Type\PasswordType(), new Type\PercentType(), new Type\RadioType(), new Type\RepeatedType(), new Type\SearchType(), new Type\TextareaType(), new Type\TextType(), new Type\TimeType(), new Type\TimezoneType(), new Type\UrlType(), new Type\FileType(), new Type\ButtonType(), new Type\SubmitType(), new Type\ResetType(), new Type\CurrencyType(), ); } } PK]-P6Form/Extension/Validator/Constraints/FormValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Constraints; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Validator\Util\ServerParams; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek */ class FormValidator extends ConstraintValidator { /** * @var ServerParams */ private $serverParams; /** * Creates a validator with the given server parameters. * * @param ServerParams $params The server parameters. Default * parameters are created if null. */ public function __construct(ServerParams $params = null) { $this->serverParams = $params ?: new ServerParams(); } /** * {@inheritdoc} */ public function validate($form, Constraint $constraint) { if (!$form instanceof FormInterface) { return; } /* @var FormInterface $form */ $config = $form->getConfig(); if ($form->isSynchronized()) { // Validate the form data only if transformation succeeded $groups = self::getValidationGroups($form); // Validate the data against its own constraints if (self::allowDataWalking($form)) { foreach ($groups as $group) { $this->context->validate($form->getData(), 'data', $group, true); } } // Validate the data against the constraints defined // in the form $constraints = $config->getOption('constraints'); foreach ($constraints as $constraint) { foreach ($groups as $group) { if (in_array($group, $constraint->groups)) { $this->context->validateValue($form->getData(), $constraint, 'data', $group); // Prevent duplicate validation continue 2; } } } } else { $childrenSynchronized = true; foreach ($form as $child) { if (!$child->isSynchronized()) { $childrenSynchronized = false; break; } } // Mark the form with an error if it is not synchronized BUT all // of its children are synchronized. If any child is not // synchronized, an error is displayed there already and showing // a second error in its parent form is pointless, or worse, may // lead to duplicate errors if error bubbling is enabled on the // child. // See also https://github.com/symfony/symfony/issues/4359 if ($childrenSynchronized) { $clientDataAsString = is_scalar($form->getViewData()) ? (string) $form->getViewData() : gettype($form->getViewData()); $this->context->addViolation( $config->getOption('invalid_message'), array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')), $form->getViewData(), null, Form::ERR_INVALID ); } } // Mark the form with an error if it contains extra fields if (count($form->getExtraData()) > 0) { $this->context->addViolation( $config->getOption('extra_fields_message'), array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), $form->getExtraData() ); } // Mark the form with an error if the uploaded size was too large $length = $this->serverParams->getContentLength(); if ($form->isRoot() && null !== $length) { $max = $this->serverParams->getPostMaxSize(); if (!empty($max) && $length > $max) { $this->context->addViolation( $config->getOption('post_max_size_message'), array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()), $length ); } } } /** * Returns whether the data of a form may be walked. * * @param FormInterface $form The form to test. * * @return Boolean Whether the graph walker may walk the data. */ private static function allowDataWalking(FormInterface $form) { $data = $form->getData(); // Scalar values cannot have mapped constraints if (!is_object($data) && !is_array($data)) { return false; } // Root forms are always validated if ($form->isRoot()) { return true; } // Non-root forms are validated if validation cascading // is enabled in all ancestor forms while (null !== ($form = $form->getParent())) { if (!$form->getConfig()->getOption('cascade_validation')) { return false; } } return true; } /** * Returns the validation groups of the given form. * * @param FormInterface $form The form. * * @return array The validation groups. */ private static function getValidationGroups(FormInterface $form) { // Determine the clicked button of the complete form tree $clickedButton = null; if (method_exists($form, 'getClickedButton')) { $clickedButton = $form->getClickedButton(); } if (null !== $clickedButton) { $groups = $clickedButton->getConfig()->getOption('validation_groups'); if (null !== $groups) { return self::resolveValidationGroups($groups, $form); } } do { $groups = $form->getConfig()->getOption('validation_groups'); if (null !== $groups) { return self::resolveValidationGroups($groups, $form); } $form = $form->getParent(); } while (null !== $form); return array(Constraint::DEFAULT_GROUP); } /** * Post-processes the validation groups option for a given form. * * @param array|callable $groups The validation groups. * @param FormInterface $form The validated form. * * @return array The validation groups. */ private static function resolveValidationGroups($groups, FormInterface $form) { if (!is_string($groups) && is_callable($groups)) { $groups = call_user_func($groups, $form); } return (array) $groups; } } PK]}>ُ-Form/Extension/Validator/Constraints/Form.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @author Bernhard Schussek */ class Form extends Constraint { /** * Violation code marking an invalid form. */ const ERR_INVALID = 1; /** * {@inheritdoc} */ public function getTargets() { return self::CLASS_CONSTRAINT; } } PK]8Form/Extension/Validator/Type/BaseValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * Encapsulates common logic of {@link FormTypeValidatorExtension} and * {@link SubmitTypeValidatorExtension}. * * @author Bernhard Schussek */ abstract class BaseValidatorExtension extends AbstractTypeExtension { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { // Make sure that validation groups end up as null, closure or array $validationGroupsNormalizer = function (Options $options, $groups) { if (false === $groups) { return array(); } if (empty($groups)) { return null; } if (is_callable($groups)) { return $groups; } return (array) $groups; }; $resolver->setDefaults(array( 'validation_groups' => null, )); $resolver->setNormalizers(array( 'validation_groups' => $validationGroupsNormalizer, )); } } PK]1>Form/Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; /** * @author Bernhard Schussek */ class SubmitTypeValidatorExtension extends BaseValidatorExtension { /** * {@inheritdoc} */ public function getExtendedType() { return 'submit'; } } PK]͚>@@@Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ class RepeatedTypeValidatorExtension extends AbstractTypeExtension { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { // Map errors to the first field $errorMapping = function (Options $options) { return array('.' => $options['first_name']); }; $resolver->setDefaults(array( 'error_mapping' => $errorMapping, )); } /** * {@inheritdoc} */ public function getExtendedType() { return 'repeated'; } } PK]eBR <Form/Extension/Validator/Type/FormTypeValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; use Symfony\Component\Validator\ValidatorInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ class FormTypeValidatorExtension extends BaseValidatorExtension { /** * @var ValidatorInterface */ private $validator; /** * @var ViolationMapper */ private $violationMapper; public function __construct(ValidatorInterface $validator) { $this->validator = $validator; $this->violationMapper = new ViolationMapper(); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber(new ValidationListener($this->validator, $this->violationMapper)); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { parent::setDefaultOptions($resolver); // Constraint should always be converted to an array $constraintsNormalizer = function (Options $options, $constraints) { return is_object($constraints) ? array($constraints) : (array) $constraints; }; $resolver->setDefaults(array( 'error_mapping' => array(), 'constraints' => array(), 'cascade_validation' => false, 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), 'extra_fields_message' => 'This form should not contain extra fields.', 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', )); $resolver->setNormalizers(array( 'constraints' => $constraintsNormalizer, )); } /** * {@inheritdoc} */ public function getExtendedType() { return 'form'; } } PK]lCt*t*1Form/Extension/Validator/ValidatorTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator; use Symfony\Component\Form\FormTypeGuesserInterface; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\TypeGuess; use Symfony\Component\Form\Guess\ValueGuess; use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\Constraint; class ValidatorTypeGuesser implements FormTypeGuesserInterface { private $metadataFactory; public function __construct(MetadataFactoryInterface $metadataFactory) { $this->metadataFactory = $metadataFactory; } /** * {@inheritDoc} */ public function guessType($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessTypeForConstraint($constraint); }); } /** * {@inheritDoc} */ public function guessRequired($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessRequiredForConstraint($constraint); // If we don't find any constraint telling otherwise, we can assume // that a field is not required (with LOW_CONFIDENCE) }, false); } /** * {@inheritDoc} */ public function guessMaxLength($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessMaxLengthForConstraint($constraint); }); } /** * {@inheritDoc} */ public function guessPattern($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessPatternForConstraint($constraint); }); } /** * Guesses a field class name for a given constraint * * @param Constraint $constraint The constraint to guess for * * @return TypeGuess|null The guessed field class and options */ public function guessTypeForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\Type': switch ($constraint->type) { case 'array': return new TypeGuess('collection', array(), Guess::MEDIUM_CONFIDENCE); case 'boolean': case 'bool': return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE); case 'double': case 'float': case 'numeric': case 'real': return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE); case 'integer': case 'int': case 'long': return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE); case '\DateTime': return new TypeGuess('date', array(), Guess::MEDIUM_CONFIDENCE); case 'string': return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Country': return new TypeGuess('country', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Date': return new TypeGuess('date', array('input' => 'string'), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\DateTime': return new TypeGuess('datetime', array('input' => 'string'), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Email': return new TypeGuess('email', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\File': case 'Symfony\Component\Validator\Constraints\Image': return new TypeGuess('file', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Language': return new TypeGuess('language', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Locale': return new TypeGuess('locale', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Time': return new TypeGuess('time', array('input' => 'string'), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Url': return new TypeGuess('url', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Ip': return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Length': case 'Symfony\Component\Validator\Constraints\Regex': return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Range': return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Count': return new TypeGuess('collection', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\True': case 'Symfony\Component\Validator\Constraints\False': return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE); } return null; } /** * Guesses whether a field is required based on the given constraint * * @param Constraint $constraint The constraint to guess for * * @return ValueGuess|null The guess whether the field is required */ public function guessRequiredForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\NotNull': case 'Symfony\Component\Validator\Constraints\NotBlank': case 'Symfony\Component\Validator\Constraints\True': return new ValueGuess(true, Guess::HIGH_CONFIDENCE); } return null; } /** * Guesses a field's maximum length based on the given constraint * * @param Constraint $constraint The constraint to guess for * * @return ValueGuess|null The guess for the maximum length */ public function guessMaxLengthForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\Length': if (is_numeric($constraint->max)) { return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Type': if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Range': if (is_numeric($constraint->max)) { return new ValueGuess(strlen((string) $constraint->max), Guess::LOW_CONFIDENCE); } break; } return null; } /** * Guesses a field's pattern based on the given constraint * * @param Constraint $constraint The constraint to guess for * * @return ValueGuess|null The guess for the pattern */ public function guessPatternForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\Length': if (is_numeric($constraint->min)) { return new ValueGuess(sprintf('.{%s,}', (string) $constraint->min), Guess::LOW_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Regex': $htmlPattern = $constraint->getHtmlPattern(); if (null !== $htmlPattern) { return new ValueGuess($htmlPattern, Guess::HIGH_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Range': if (is_numeric($constraint->min)) { return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->min)), Guess::LOW_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Type': if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } break; } return null; } /** * Iterates over the constraints of a property, executes a constraints on * them and returns the best guess * * @param string $class The class to read the constraints from * @param string $property The property for which to find constraints * @param \Closure $closure The closure that returns a guess * for a given constraint * @param mixed $defaultValue The default value assumed if no other value * can be guessed. * * @return Guess|null The guessed value with the highest confidence */ protected function guess($class, $property, \Closure $closure, $defaultValue = null) { $guesses = array(); $classMetadata = $this->metadataFactory->getMetadataFor($class); if ($classMetadata->hasMemberMetadatas($property)) { $memberMetadatas = $classMetadata->getMemberMetadatas($property); foreach ($memberMetadatas as $memberMetadata) { $constraints = $memberMetadata->getConstraints(); foreach ($constraints as $constraint) { if ($guess = $closure($constraint)) { $guesses[] = $guess; } } } if (null !== $defaultValue) { $guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE); } } return Guess::getBestGuess($guesses); } } PK]Ck.Form/Extension/Validator/Util/ServerParams.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Util; /** * @author Bernhard Schussek */ class ServerParams { /** * Returns maximum post size in bytes. * * @return null|integer The maximum post size in bytes */ public function getPostMaxSize() { $iniMax = strtolower($this->getNormalizedIniPostMaxSize()); if ('' === $iniMax) { return null; } $max = ltrim($iniMax, '+'); if (0 === strpos($max, '0x')) { $max = intval($max, 16); } elseif (0 === strpos($max, '0')) { $max = intval($max, 8); } else { $max = intval($max); } switch (substr($iniMax, -1)) { case 't': $max *= 1024; case 'g': $max *= 1024; case 'm': $max *= 1024; case 'k': $max *= 1024; } return $max; } /** * Returns the normalized "post_max_size" ini setting. * * @return string */ public function getNormalizedIniPostMaxSize() { return strtoupper(trim(ini_get('post_max_size'))); } /** * Returns the content length of the request. * * @return mixed The request content length. */ public function getContentLength() { return isset($_SERVER['CONTENT_LENGTH']) ? (int) $_SERVER['CONTENT_LENGTH'] : null; } } PK]*=Form/Extension/Validator/EventListener/ValidationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface; use Symfony\Component\Validator\ValidatorInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Validator\Constraints\Form; /** * @author Bernhard Schussek */ class ValidationListener implements EventSubscriberInterface { private $validator; private $violationMapper; /** * {@inheritdoc} */ public static function getSubscribedEvents() { return array(FormEvents::POST_SUBMIT => 'validateForm'); } public function __construct(ValidatorInterface $validator, ViolationMapperInterface $violationMapper) { $this->validator = $validator; $this->violationMapper = $violationMapper; } /** * Validates the form and its domain object. * * @param FormEvent $event The event object */ public function validateForm(FormEvent $event) { $form = $event->getForm(); if ($form->isRoot()) { // Validate the form in group "Default" $violations = $this->validator->validate($form); foreach ($violations as $violation) { // Allow the "invalid" constraint to be put onto // non-synchronized forms $allowNonSynchronized = Form::ERR_INVALID === $violation->getCode(); $this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized); } } } } PK]2=[<((/Form/Extension/Validator/ValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Validator\ValidatorInterface; use Symfony\Component\Validator\Constraints\Valid; /** * Extension supporting the Symfony2 Validator component in forms. * * @author Bernhard Schussek */ class ValidatorExtension extends AbstractExtension { private $validator; public function __construct(ValidatorInterface $validator) { $this->validator = $validator; // Register the form constraints in the validator programmatically. // This functionality is required when using the Form component without // the DIC, where the XML file is loaded automatically. Thus the following // code must be kept synchronized with validation.xml /** @var \Symfony\Component\Validator\Mapping\ClassMetadata $metadata */ $metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form'); $metadata->addConstraint(new Form()); $metadata->addPropertyConstraint('children', new Valid()); } public function loadTypeGuesser() { return new ValidatorTypeGuesser($this->validator->getMetadataFactory()); } protected function loadTypeExtensions() { return array( new Type\FormTypeValidatorExtension($this->validator), new Type\RepeatedTypeValidatorExtension(), new Type\SubmitTypeValidatorExtension(), ); } } PK]-!!:Form/Extension/Validator/ViolationMapper/ViolationPath.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\Exception\OutOfBoundsException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\PropertyPathInterface; /** * @author Bernhard Schussek */ class ViolationPath implements \IteratorAggregate, PropertyPathInterface { /** * @var array */ private $elements = array(); /** * @var array */ private $isIndex = array(); /** * @var array */ private $mapsForm = array(); /** * @var string */ private $pathAsString = ''; /** * @var integer */ private $length = 0; /** * Creates a new violation path from a string. * * @param string $violationPath The property path of a {@link ConstraintViolation} * object. */ public function __construct($violationPath) { $path = new PropertyPath($violationPath); $elements = $path->getElements(); $data = false; for ($i = 0, $l = count($elements); $i < $l; ++$i) { if (!$data) { // The element "data" has not yet been passed if ('children' === $elements[$i] && $path->isProperty($i)) { // Skip element "children" ++$i; // Next element must exist and must be an index // Otherwise consider this the end of the path if ($i >= $l || !$path->isIndex($i)) { break; } $this->elements[] = $elements[$i]; $this->isIndex[] = true; $this->mapsForm[] = true; } elseif ('data' === $elements[$i] && $path->isProperty($i)) { // Skip element "data" ++$i; // End of path if ($i >= $l) { break; } $this->elements[] = $elements[$i]; $this->isIndex[] = $path->isIndex($i); $this->mapsForm[] = false; $data = true; } else { // Neither "children" nor "data" property found // Consider this the end of the path break; } } else { // Already after the "data" element // Pick everything as is $this->elements[] = $elements[$i]; $this->isIndex[] = $path->isIndex($i); $this->mapsForm[] = false; } } $this->length = count($this->elements); $this->buildString(); } /** * {@inheritdoc} */ public function __toString() { return $this->pathAsString; } /** * {@inheritdoc} */ public function getLength() { return $this->length; } /** * {@inheritdoc} */ public function getParent() { if ($this->length <= 1) { return null; } $parent = clone $this; --$parent->length; array_pop($parent->elements); array_pop($parent->isIndex); array_pop($parent->mapsForm); $parent->buildString(); return $parent; } /** * {@inheritdoc} */ public function getElements() { return $this->elements; } /** * {@inheritdoc} */ public function getElement($index) { if (!isset($this->elements[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->elements[$index]; } /** * {@inheritdoc} */ public function isProperty($index) { if (!isset($this->isIndex[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return !$this->isIndex[$index]; } /** * {@inheritdoc} */ public function isIndex($index) { if (!isset($this->isIndex[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->isIndex[$index]; } /** * Returns whether an element maps directly to a form. * * Consider the following violation path: * * * children[address].children[office].data.street * * * In this example, "address" and "office" map to forms, while * "street does not. * * @param integer $index The element index. * * @return Boolean Whether the element maps to a form. * * @throws OutOfBoundsException If the offset is invalid. */ public function mapsForm($index) { if (!isset($this->mapsForm[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->mapsForm[$index]; } /** * Returns a new iterator for this path * * @return ViolationPathIterator */ public function getIterator() { return new ViolationPathIterator($this); } /** * Builds the string representation from the elements. */ private function buildString() { $this->pathAsString = ''; $data = false; foreach ($this->elements as $index => $element) { if ($this->mapsForm[$index]) { $this->pathAsString .= ".children[$element]"; } elseif (!$data) { $this->pathAsString .= '.data'.($this->isIndex[$index] ? "[$element]" : ".$element"); $data = true; } else { $this->pathAsString .= $this->isIndex[$index] ? "[$element]" : ".$element"; } } if ('' !== $this->pathAsString) { // remove leading dot $this->pathAsString = substr($this->pathAsString, 1); } } } PK]f 8Form/Extension/Validator/ViolationMapper/MappingRule.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Exception\ErrorMappingException; /** * @author Bernhard Schussek */ class MappingRule { /** * @var FormInterface */ private $origin; /** * @var string */ private $propertyPath; /** * @var string */ private $targetPath; public function __construct(FormInterface $origin, $propertyPath, $targetPath) { $this->origin = $origin; $this->propertyPath = $propertyPath; $this->targetPath = $targetPath; } /** * @return FormInterface */ public function getOrigin() { return $this->origin; } /** * Matches a property path against the rule path. * * If the rule matches, the form mapped by the rule is returned. * Otherwise this method returns false. * * @param string $propertyPath The property path to match against the rule. * * @return null|FormInterface The mapped form or null. */ public function match($propertyPath) { if ($propertyPath === (string) $this->propertyPath) { return $this->getTarget(); } return null; } /** * Matches a property path against a prefix of the rule path. * * @param string $propertyPath The property path to match against the rule. * * @return Boolean Whether the property path is a prefix of the rule or not. */ public function isPrefix($propertyPath) { $length = strlen($propertyPath); $prefix = substr($this->propertyPath, 0, $length); $next = isset($this->propertyPath[$length]) ? $this->propertyPath[$length] : null; return $prefix === $propertyPath && ('[' === $next || '.' === $next); } /** * @return FormInterface * * @throws ErrorMappingException */ public function getTarget() { $childNames = explode('.', $this->targetPath); $target = $this->origin; foreach ($childNames as $childName) { if (!$target->has($childName)) { throw new ErrorMappingException(sprintf('The child "%s" of "%s" mapped by the rule "%s" in "%s" does not exist.', $childName, $target->getName(), $this->targetPath, $this->origin->getName())); } $target = $target->get($childName); } return $target; } } PK]kt==EForm/Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\Validator\ConstraintViolation; /** * @author Bernhard Schussek */ interface ViolationMapperInterface { /** * Maps a constraint violation to a form in the form tree under * the given form. * * @param ConstraintViolation $violation The violation to map. * @param FormInterface $form The root form of the tree * to map it to. * @param Boolean $allowNonSynchronized Whether to allow * mapping to non-synchronized forms. */ public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false); } PK]\T9Form/Extension/Validator/ViolationMapper/RelativePath.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\PropertyAccess\PropertyPath; /** * @author Bernhard Schussek */ class RelativePath extends PropertyPath { /** * @var FormInterface */ private $root; /** * @param FormInterface $root * @param string $propertyPath */ public function __construct(FormInterface $root, $propertyPath) { parent::__construct($propertyPath); $this->root = $root; } /** * @return FormInterface */ public function getRoot() { return $this->root; } } PK]ɥSBForm/Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\PropertyAccess\PropertyPathIterator; /** * @author Bernhard Schussek */ class ViolationPathIterator extends PropertyPathIterator { public function __construct(ViolationPath $violationPath) { parent::__construct($violationPath); } public function mapsForm() { return $this->path->mapsForm($this->key()); } } PK]C_hU+U+<Form/Extension/Validator/ViolationMapper/ViolationMapper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Util\InheritDataAwareIterator; use Symfony\Component\PropertyAccess\PropertyPathIterator; use Symfony\Component\PropertyAccess\PropertyPathBuilder; use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface; use Symfony\Component\Form\FormError; use Symfony\Component\Validator\ConstraintViolation; /** * @author Bernhard Schussek */ class ViolationMapper implements ViolationMapperInterface { /** * @var Boolean */ private $allowNonSynchronized; /** * {@inheritdoc} */ public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false) { $this->allowNonSynchronized = $allowNonSynchronized; // The scope is the currently found most specific form that // an error should be mapped to. After setting the scope, the // mapper will try to continue to find more specific matches in // the children of scope. If it cannot, the error will be // mapped to this scope. $scope = null; $violationPath = null; $relativePath = null; $match = false; // Don't create a ViolationPath instance for empty property paths if (strlen($violation->getPropertyPath()) > 0) { $violationPath = new ViolationPath($violation->getPropertyPath()); $relativePath = $this->reconstructPath($violationPath, $form); } // This case happens if the violation path is empty and thus // the violation should be mapped to the root form if (null === $violationPath) { $scope = $form; } // In general, mapping happens from the root form to the leaf forms // First, the rules of the root form are applied to determine // the subsequent descendant. The rules of this descendant are then // applied to find the next and so on, until we have found the // most specific form that matches the violation. // If any of the forms found in this process is not synchronized, // mapping is aborted. Non-synchronized forms could not reverse // transform the value entered by the user, thus any further violations // caused by the (invalid) reverse transformed value should be // ignored. if (null !== $relativePath) { // Set the scope to the root of the relative path // This root will usually be $form. If the path contains // an unmapped form though, the last unmapped form found // will be the root of the path. $scope = $relativePath->getRoot(); $it = new PropertyPathIterator($relativePath); while ($this->acceptsErrors($scope) && null !== ($child = $this->matchChild($scope, $it))) { $scope = $child; $it->next(); $match = true; } } // This case happens if an error happened in the data under a // form inheriting its parent data that does not match any of the // children of that form. if (null !== $violationPath && !$match) { // If we could not map the error to anything more specific // than the root element, map it to the innermost directly // mapped form of the violation path // e.g. "children[foo].children[bar].data.baz" // Here the innermost directly mapped child is "bar" $scope = $form; $it = new ViolationPathIterator($violationPath); // Note: acceptsErrors() will always return true for forms inheriting // their parent data, because these forms can never be non-synchronized // (they don't do any data transformation on their own) while ($this->acceptsErrors($scope) && $it->valid() && $it->mapsForm()) { if (!$scope->has($it->current())) { // Break if we find a reference to a non-existing child break; } $scope = $scope->get($it->current()); $it->next(); } } // Follow dot rules until we have the final target $mapping = $scope->getConfig()->getOption('error_mapping'); while ($this->acceptsErrors($scope) && isset($mapping['.'])) { $dotRule = new MappingRule($scope, '.', $mapping['.']); $scope = $dotRule->getTarget(); $mapping = $scope->getConfig()->getOption('error_mapping'); } // Only add the error if the form is synchronized if ($this->acceptsErrors($scope)) { $scope->addError(new FormError( $violation->getMessage(), $violation->getMessageTemplate(), $violation->getMessageParameters(), $violation->getMessagePluralization() )); } } /** * Tries to match the beginning of the property path at the * current position against the children of the scope. * * If a matching child is found, it is returned. Otherwise * null is returned. * * @param FormInterface $form The form to search. * @param PropertyPathIteratorInterface $it The iterator at its current position. * * @return null|FormInterface The found match or null. */ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $it) { // Remember at what property path underneath "data" // we are looking. Check if there is a child with that // path, otherwise increase path by one more piece $chunk = ''; $foundChild = null; $foundAtIndex = 0; // Construct mapping rules for the given form $rules = array(); foreach ($form->getConfig()->getOption('error_mapping') as $propertyPath => $targetPath) { // Dot rules are considered at the very end if ('.' !== $propertyPath) { $rules[] = new MappingRule($form, $propertyPath, $targetPath); } } // Skip forms inheriting their parent data when iterating the children $childIterator = new \RecursiveIteratorIterator( new InheritDataAwareIterator($form) ); // Make the path longer until we find a matching child while (true) { if (!$it->valid()) { return null; } if ($it->isIndex()) { $chunk .= '['.$it->current().']'; } else { $chunk .= ('' === $chunk ? '' : '.').$it->current(); } // Test mapping rules as long as we have any foreach ($rules as $key => $rule) { /* @var MappingRule $rule */ // Mapping rule matches completely, terminate. if (null !== ($form = $rule->match($chunk))) { return $form; } // Keep only rules that have $chunk as prefix if (!$rule->isPrefix($chunk)) { unset($rules[$key]); } } // Test children unless we already found one if (null === $foundChild) { foreach ($childIterator as $child) { /* @var FormInterface $child */ $childPath = (string) $child->getPropertyPath(); // Child found, mark as return value if ($chunk === $childPath) { $foundChild = $child; $foundAtIndex = $it->key(); } } } // Add element to the chunk $it->next(); // If we reached the end of the path or if there are no // more matching mapping rules, return the found child if (null !== $foundChild && (!$it->valid() || count($rules) === 0)) { // Reset index in case we tried to find mapping // rules further down the path $it->seek($foundAtIndex); return $foundChild; } } return null; } /** * Reconstructs a property path from a violation path and a form tree. * * @param ViolationPath $violationPath The violation path. * @param FormInterface $origin The root form of the tree. * * @return RelativePath The reconstructed path. */ private function reconstructPath(ViolationPath $violationPath, FormInterface $origin) { $propertyPathBuilder = new PropertyPathBuilder($violationPath); $it = $violationPath->getIterator(); $scope = $origin; // Remember the current index in the builder $i = 0; // Expand elements that map to a form (like "children[address]") for ($it->rewind(); $it->valid() && $it->mapsForm(); $it->next()) { if (!$scope->has($it->current())) { // Scope relates to a form that does not exist // Bail out break; } // Process child form $scope = $scope->get($it->current()); if ($scope->getConfig()->getInheritData()) { // Form inherits its parent data // Cut the piece out of the property path and proceed $propertyPathBuilder->remove($i); } elseif (!$scope->getConfig()->getMapped()) { // Form is not mapped // Set the form as new origin and strip everything // we have so far in the path $origin = $scope; $propertyPathBuilder->remove(0, $i + 1); $i = 0; } else { /* @var \Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath */ $propertyPath = $scope->getPropertyPath(); if (null === $propertyPath) { // Property path of a mapped form is null // Should not happen, bail out break; } $propertyPathBuilder->replace($i, 1, $propertyPath); $i += $propertyPath->getLength(); } } $finalPath = $propertyPathBuilder->getPropertyPath(); return null !== $finalPath ? new RelativePath($origin, $finalPath) : null; } /** * @param FormInterface $form * * @return Boolean */ private function acceptsErrors(FormInterface $form) { return $this->allowNonSynchronized || $form->isSynchronized(); } } PK]E Form/FormRendererInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Renders a form into HTML. * * @author Bernhard Schussek */ interface FormRendererInterface { /** * Returns the engine used by this renderer. * * @return FormRendererEngineInterface The renderer engine. */ public function getEngine(); /** * Sets the theme(s) to be used for rendering a view and its children. * * @param FormView $view The view to assign the theme(s) to. * @param mixed $themes The theme(s). The type of these themes * is open to the implementation. */ public function setTheme(FormView $view, $themes); /** * Renders a named block of the form theme. * * @param FormView $view The view for which to render the block. * @param string $blockName The name of the block. * @param array $variables The variables to pass to the template. * * @return string The HTML markup */ public function renderBlock(FormView $view, $blockName, array $variables = array()); /** * Searches and renders a block for a given name suffix. * * The block is searched by combining the block names stored in the * form view with the given suffix. If a block name is found, that * block is rendered. * * If this method is called recursively, the block search is continued * where a block was found before. * * @param FormView $view The view for which to render the block. * @param string $blockNameSuffix The suffix of the block name. * @param array $variables The variables to pass to the template. * * @return string The HTML markup */ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $variables = array()); /** * Renders a CSRF token. * * Use this helper for CSRF protection without the overhead of creating a * form. * * * * * * Check the token in your action using the same token ID. * * * $csrfProvider = $this->get('security.csrf.token_generator'); * if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) { * throw new \RuntimeException('CSRF attack detected.'); * } * * * @param string $tokenId The ID of the CSRF token * * @return string A CSRF token */ public function renderCsrfToken($tokenId); /** * Makes a technical name human readable. * * Sequences of underscores are replaced by single spaces. The first letter * of the resulting string is capitalized, while all other letters are * turned to lowercase. * * @param string $text The text to humanize. * * @return string The humanized text. */ public function humanize($text); } PK]:  Form/FormBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface FormBuilderInterface extends \Traversable, \Countable, FormConfigBuilderInterface { /** * Adds a new field to this group. A field must have a unique name within * the group. Otherwise the existing field is overwritten. * * If you add a nested group, this group should also be represented in the * object hierarchy. * * @param string|integer|FormBuilderInterface $child * @param string|FormTypeInterface $type * @param array $options * * @return FormBuilderInterface The builder object. */ public function add($child, $type = null, array $options = array()); /** * Creates a form builder. * * @param string $name The name of the form or the name of the property * @param string|FormTypeInterface $type The type of the form or null if name is a property * @param array $options The options * * @return FormBuilderInterface The created builder. */ public function create($name, $type = null, array $options = array()); /** * Returns a child by name. * * @param string $name The name of the child * * @return FormBuilderInterface The builder for the child * * @throws Exception\InvalidArgumentException if the given child does not exist */ public function get($name); /** * Removes the field with the given name. * * @param string $name * * @return FormBuilderInterface The builder object. */ public function remove($name); /** * Returns whether a field with the given name exists. * * @param string $name * * @return Boolean */ public function has($name); /** * Returns the children. * * @return array */ public function all(); /** * Creates the form. * * @return Form The form */ public function getForm(); } PK]QTppForm/SubmitButtonBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A builder for {@link SubmitButton} instances. * * @author Bernhard Schussek */ class SubmitButtonBuilder extends ButtonBuilder { /** * Creates the button. * * @return SubmitButton The button */ public function getForm() { return new SubmitButton($this->getFormConfig()); } } PK]>*iiForm/FormFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; class FormFactory implements FormFactoryInterface { /** * @var FormRegistryInterface */ private $registry; /** * @var ResolvedFormTypeFactoryInterface */ private $resolvedTypeFactory; public function __construct(FormRegistryInterface $registry, ResolvedFormTypeFactoryInterface $resolvedTypeFactory) { $this->registry = $registry; $this->resolvedTypeFactory = $resolvedTypeFactory; } /** * {@inheritdoc} */ public function create($type = 'form', $data = null, array $options = array()) { return $this->createBuilder($type, $data, $options)->getForm(); } /** * {@inheritdoc} */ public function createNamed($name, $type = 'form', $data = null, array $options = array()) { return $this->createNamedBuilder($name, $type, $data, $options)->getForm(); } /** * {@inheritdoc} */ public function createForProperty($class, $property, $data = null, array $options = array()) { return $this->createBuilderForProperty($class, $property, $data, $options)->getForm(); } /** * {@inheritdoc} */ public function createBuilder($type = 'form', $data = null, array $options = array()) { $name = $type instanceof FormTypeInterface || $type instanceof ResolvedFormTypeInterface ? $type->getName() : $type; return $this->createNamedBuilder($name, $type, $data, $options); } /** * {@inheritdoc} */ public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array()) { if (null !== $data && !array_key_exists('data', $options)) { $options['data'] = $data; } if ($type instanceof FormTypeInterface) { $type = $this->resolveType($type); } elseif (is_string($type)) { $type = $this->registry->getType($type); } elseif (!$type instanceof ResolvedFormTypeInterface) { throw new UnexpectedTypeException($type, 'string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface'); } $builder = $type->createBuilder($this, $name, $options); // Explicitly call buildForm() in order to be able to override either // createBuilder() or buildForm() in the resolved form type $type->buildForm($builder, $builder->getOptions()); return $builder; } /** * {@inheritdoc} */ public function createBuilderForProperty($class, $property, $data = null, array $options = array()) { if (null === $guesser = $this->registry->getTypeGuesser()) { return $this->createNamedBuilder($property, 'text', $data, $options); } $typeGuess = $guesser->guessType($class, $property); $maxLengthGuess = $guesser->guessMaxLength($class, $property); $requiredGuess = $guesser->guessRequired($class, $property); $patternGuess = $guesser->guessPattern($class, $property); $type = $typeGuess ? $typeGuess->getType() : 'text'; $maxLength = $maxLengthGuess ? $maxLengthGuess->getValue() : null; $pattern = $patternGuess ? $patternGuess->getValue() : null; if (null !== $pattern) { $options = array_merge(array('pattern' => $pattern), $options); } if (null !== $maxLength) { $options = array_merge(array('max_length' => $maxLength), $options); } if ($requiredGuess) { $options = array_merge(array('required' => $requiredGuess->getValue()), $options); } // user options may override guessed options if ($typeGuess) { $options = array_merge($typeGuess->getOptions(), $options); } return $this->createNamedBuilder($property, $type, $data, $options); } /** * Wraps a type into a ResolvedFormTypeInterface implementation and connects * it with its parent type. * * @param FormTypeInterface $type The type to resolve. * * @return ResolvedFormTypeInterface The resolved type. */ private function resolveType(FormTypeInterface $type) { $parentType = $type->getParent(); if ($parentType instanceof FormTypeInterface) { $parentType = $this->resolveType($parentType); } elseif (null !== $parentType) { $parentType = $this->registry->getType($parentType); } return $this->resolvedTypeFactory->createResolvedType( $type, // Type extensions are not supported for unregistered type instances, // i.e. type instances that are passed to the FormFactory directly, // nor for their parents, if getParent() also returns a type instance. array(), $parentType ); } } PK]ÊM'%%Form/FormConfigInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * The configuration of a {@link Form} object. * * @author Bernhard Schussek */ interface FormConfigInterface { /** * Returns the event dispatcher used to dispatch form events. * * @return \Symfony\Component\EventDispatcher\EventDispatcherInterface The dispatcher. */ public function getEventDispatcher(); /** * Returns the name of the form used as HTTP parameter. * * @return string The form name. */ public function getName(); /** * Returns the property path that the form should be mapped to. * * @return null|\Symfony\Component\PropertyAccess\PropertyPathInterface The property path. */ public function getPropertyPath(); /** * Returns whether the form should be mapped to an element of its * parent's data. * * @return Boolean Whether the form is mapped. */ public function getMapped(); /** * Returns whether the form's data should be modified by reference. * * @return Boolean Whether to modify the form's data by reference. */ public function getByReference(); /** * Returns whether the form should read and write the data of its parent. * * @return Boolean Whether the form should inherit its parent's data. */ public function getInheritData(); /** * Returns whether the form is compound. * * This property is independent of whether the form actually has * children. A form can be compound and have no children at all, like * for example an empty collection form. * * @return Boolean Whether the form is compound. */ public function getCompound(); /** * Returns the form types used to construct the form. * * @return ResolvedFormTypeInterface The form's type. */ public function getType(); /** * Returns the view transformers of the form. * * @return DataTransformerInterface[] An array of {@link DataTransformerInterface} instances. */ public function getViewTransformers(); /** * Returns the model transformers of the form. * * @return DataTransformerInterface[] An array of {@link DataTransformerInterface} instances. */ public function getModelTransformers(); /** * Returns the data mapper of the form. * * @return DataMapperInterface The data mapper. */ public function getDataMapper(); /** * Returns whether the form is required. * * @return Boolean Whether the form is required. */ public function getRequired(); /** * Returns whether the form is disabled. * * @return Boolean Whether the form is disabled. */ public function getDisabled(); /** * Returns whether errors attached to the form will bubble to its parent. * * @return Boolean Whether errors will bubble up. */ public function getErrorBubbling(); /** * Returns the data that should be returned when the form is empty. * * @return mixed The data returned if the form is empty. */ public function getEmptyData(); /** * Returns additional attributes of the form. * * @return array An array of key-value combinations. */ public function getAttributes(); /** * Returns whether the attribute with the given name exists. * * @param string $name The attribute name. * * @return Boolean Whether the attribute exists. */ public function hasAttribute($name); /** * Returns the value of the given attribute. * * @param string $name The attribute name. * @param mixed $default The value returned if the attribute does not exist. * * @return mixed The attribute value. */ public function getAttribute($name, $default = null); /** * Returns the initial data of the form. * * @return mixed The initial form data. */ public function getData(); /** * Returns the class of the form data or null if the data is scalar or an array. * * @return string The data class or null. */ public function getDataClass(); /** * Returns whether the form's data is locked. * * A form with locked data is restricted to the data passed in * this configuration. The data can only be modified then by * submitting the form. * * @return Boolean Whether the data is locked. */ public function getDataLocked(); /** * Returns the form factory used for creating new forms. * * @return FormFactoryInterface The form factory. */ public function getFormFactory(); /** * Returns the target URL of the form. * * @return string The target URL of the form. */ public function getAction(); /** * Returns the HTTP method used by the form. * * @return string The HTTP method of the form. */ public function getMethod(); /** * Returns the request handler used by the form. * * @return RequestHandlerInterface The request handler. */ public function getRequestHandler(); /** * Returns whether the form should be initialized upon creation. * * @return Boolean Returns true if the form should be initialized * when created, false otherwise. */ public function getAutoInitialize(); /** * Returns all options passed during the construction of the form. * * @return array The passed options. */ public function getOptions(); /** * Returns whether a specific option exists. * * @param string $name The option name, * * @return Boolean Whether the option exists. */ public function hasOption($name); /** * Returns the value of a specific option. * * @param string $name The option name. * @param mixed $default The value returned if the option does not exist. * * @return mixed The option value. */ public function getOption($name, $default = null); } PK]ɃT $Form/FormFactoryBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A builder for FormFactoryInterface objects. * * @author Bernhard Schussek */ interface FormFactoryBuilderInterface { /** * Sets the factory for creating ResolvedFormTypeInterface instances. * * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory * * @return FormFactoryBuilderInterface The builder. */ public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory); /** * Adds an extension to be loaded by the factory. * * @param FormExtensionInterface $extension The extension. * * @return FormFactoryBuilderInterface The builder. */ public function addExtension(FormExtensionInterface $extension); /** * Adds a list of extensions to be loaded by the factory. * * @param FormExtensionInterface[] $extensions The extensions. * * @return FormFactoryBuilderInterface The builder. */ public function addExtensions(array $extensions); /** * Adds a form type to the factory. * * @param FormTypeInterface $type The form type. * * @return FormFactoryBuilderInterface The builder. */ public function addType(FormTypeInterface $type); /** * Adds a list of form types to the factory. * * @param FormTypeInterface[] $types The form types. * * @return FormFactoryBuilderInterface The builder. */ public function addTypes(array $types); /** * Adds a form type extension to the factory. * * @param FormTypeExtensionInterface $typeExtension The form type extension. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeExtension(FormTypeExtensionInterface $typeExtension); /** * Adds a list of form type extensions to the factory. * * @param FormTypeExtensionInterface[] $typeExtensions The form type extensions. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeExtensions(array $typeExtensions); /** * Adds a type guesser to the factory. * * @param FormTypeGuesserInterface $typeGuesser The type guesser. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser); /** * Adds a list of type guessers to the factory. * * @param FormTypeGuesserInterface[] $typeGuessers The type guessers. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeGuessers(array $typeGuessers); /** * Builds and returns the factory. * * @return FormFactoryInterface The form factory. */ public function getFormFactory(); } PK](s //Form/ClickableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A clickable form element. * * @author Bernhard Schussek */ interface ClickableInterface { /** * Returns whether this element was clicked. * * @return Boolean Whether this element was clicked. */ public function isClicked(); } PK] ͋  Form/Forms.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Extension\Core\CoreExtension; /** * Entry point of the Form component. * * Use this class to conveniently create new form factories: * * * use Symfony\Component\Form\Forms; * * $formFactory = Forms::createFormFactory(); * * $form = $formFactory->createBuilder() * ->add('firstName', 'text') * ->add('lastName', 'text') * ->add('age', 'integer') * ->add('gender', 'choice', array( * 'choices' => array('m' => 'Male', 'f' => 'Female'), * )) * ->getForm(); * * * You can also add custom extensions to the form factory: * * * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new AcmeExtension()) * ->getFormFactory(); * * * If you create custom form types or type extensions, it is * generally recommended to create your own extensions that lazily * load these types and type extensions. In projects where performance * does not matter that much, you can also pass them directly to the * form factory: * * * $formFactory = Forms::createFormFactoryBuilder() * ->addType(new PersonType()) * ->addType(new PhoneNumberType()) * ->addTypeExtension(new FormTypeHelpTextExtension()) * ->getFormFactory(); * * * Support for CSRF protection is provided by the CsrfExtension. * This extension needs a CSRF provider with a strong secret * (e.g. a 20 character long random string). The default * implementation for this is DefaultCsrfProvider: * * * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; * * $secret = 'V8a5Z97e...'; * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new CsrfExtension(new DefaultCsrfProvider($secret))) * ->getFormFactory(); * * * Support for the HttpFoundation is provided by the * HttpFoundationExtension. You are also advised to load the CSRF * extension with the driver for HttpFoundation's Session class: * * * use Symfony\Component\HttpFoundation\Session\Session; * use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; * * $session = new Session(); * $secret = 'V8a5Z97e...'; * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new HttpFoundationExtension()) * ->addExtension(new CsrfExtension(new SessionCsrfProvider($session, $secret))) * ->getFormFactory(); * * * Support for the Validator component is provided by ValidatorExtension. * This extension needs a validator object to function properly: * * * use Symfony\Component\Validator\Validation; * use Symfony\Component\Form\Extension\Validator\ValidatorExtension; * * $validator = Validation::createValidator(); * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new ValidatorExtension($validator)) * ->getFormFactory(); * * * Support for the Templating component is provided by TemplatingExtension. * This extension needs a PhpEngine object for rendering forms. As second * argument you should pass the names of the default themes. Here is an * example for using the default layout with "
" tags: * * * use Symfony\Component\Form\Extension\Templating\TemplatingExtension; * * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new TemplatingExtension($engine, null, array( * 'FrameworkBundle:Form', * ))) * ->getFormFactory(); * * * The next example shows how to include the "" layout: * * * use Symfony\Component\Form\Extension\Templating\TemplatingExtension; * * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new TemplatingExtension($engine, null, array( * 'FrameworkBundle:Form', * 'FrameworkBundle:FormTable', * ))) * ->getFormFactory(); * * * If you also loaded the CsrfExtension, you should pass the CSRF provider * to the extension so that you can render CSRF tokens in your templates * more easily: * * * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; * use Symfony\Component\Form\Extension\Templating\TemplatingExtension; * * * $secret = 'V8a5Z97e...'; * $csrfProvider = new DefaultCsrfProvider($secret); * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new CsrfExtension($csrfProvider)) * ->addExtension(new TemplatingExtension($engine, $csrfProvider, array( * 'FrameworkBundle:Form', * ))) * ->getFormFactory(); * * * @author Bernhard Schussek */ final class Forms { /** * Creates a form factory with the default configuration. * * @return FormFactoryInterface The form factory. */ public static function createFormFactory() { return self::createFormFactoryBuilder()->getFormFactory(); } /** * Creates a form factory builder with the default configuration. * * @return FormFactoryBuilderInterface The form factory builder. */ public static function createFormFactoryBuilder() { $builder = new FormFactoryBuilder(); $builder->addExtension(new CoreExtension()); return $builder; } /** * This class cannot be instantiated. */ private function __construct() { } } PK] Form/FormTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ interface FormTypeInterface { /** * Builds the form. * * This method is called for each type in the hierarchy starting form the * top most type. Type extensions can further modify the form. * * @see FormTypeExtensionInterface::buildForm() * * @param FormBuilderInterface $builder The form builder * @param array $options The options */ public function buildForm(FormBuilderInterface $builder, array $options); /** * Builds the form view. * * This method is called for each type in the hierarchy starting form the * top most type. Type extensions can further modify the view. * * A view of a form is built before the views of the child forms are built. * This means that you cannot access child views in this method. If you need * to do so, move your logic to {@link finishView()} instead. * * @see FormTypeExtensionInterface::buildView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function buildView(FormView $view, FormInterface $form, array $options); /** * Finishes the form view. * * This method gets called for each type in the hierarchy starting form the * top most type. Type extensions can further modify the view. * * When this method is called, views of the form's children have already * been built and finished and can be accessed. You should only implement * such logic in this method that actually accesses child views. For everything * else you are recommended to implement {@link buildView()} instead. * * @see FormTypeExtensionInterface::finishView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function finishView(FormView $view, FormInterface $form, array $options); /** * Sets the default options for this type. * * @param OptionsResolverInterface $resolver The resolver for the options. */ public function setDefaultOptions(OptionsResolverInterface $resolver); /** * Returns the name of the parent type. * * You can also return a type instance from this method, although doing so * is discouraged because it leads to a performance penalty. The support * for returning type instances may be dropped from future releases. * * @return string|null|FormTypeInterface The name of the parent type if any, null otherwise. */ public function getParent(); /** * Returns the name of this type. * * @return string The name of this type */ public function getName(); } PK]F22&Form/Util/VirtualFormAwareIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * Iterator that traverses an array of forms. * * You can wrap the iterator into a {@link \RecursiveIterator} in order to * enter any child form that inherits its parent's data and iterate the children * of that form as well. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link InheritDataAwareIterator} instead. */ class VirtualFormAwareIterator extends \IteratorIterator implements \RecursiveIterator { /** * {@inheritdoc} */ public function getChildren() { return new static($this->current()); } /** *{@inheritdoc} */ public function hasChildren() { return (bool) $this->current()->getConfig()->getInheritData(); } } PK]I 66Form/Util/OrderedHashMap.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * A hash map which keeps track of deletions and additions. * * Like in associative arrays, elements can be mapped to integer or string keys. * Unlike associative arrays, the map keeps track of the order in which keys * were added and removed. This order is reflected during iteration. * * The map supports concurrent modification during iteration. That means that * you can insert and remove elements from within a foreach loop and the * iterator will reflect those changes accordingly. * * While elements that are added during the loop are recognized by the iterator, * changed elements are not. Otherwise the loop could be infinite if each loop * changes the current element: * * $map = new OrderedHashMap(); * $map[1] = 1; * $map[2] = 2; * $map[3] = 3; * * foreach ($map as $index => $value) { * echo "$index: $value\n" * if (1 === $index) { * $map[1] = 4; * $map[] = 5; * } * } * * print_r(iterator_to_array($map)); * * // => 1: 1 * // 2: 2 * // 3: 3 * // 4: 5 * // Array * // ( * // [1] => 4 * // [2] => 2 * // [3] => 3 * // [4] => 5 * // ) * * The map also supports multiple parallel iterators. That means that you can * nest foreach loops without affecting each other's iteration: * * foreach ($map as $index => $value) { * foreach ($map as $index2 => $value2) { * // ... * } * } * * @author Bernhard Schussek * * @since 2.2.6 */ class OrderedHashMap implements \ArrayAccess, \IteratorAggregate, \Countable { /** * The elements of the map, indexed by their keys. * * @var array */ private $elements = array(); /** * The keys of the map in the order in which they were inserted or changed. * * @var array */ private $orderedKeys = array(); /** * References to the cursors of all open iterators. * * @var array */ private $managedCursors = array(); /** * Creates a new map. * * @param array $elements The elements to insert initially. * * @since 2.2.6 */ public function __construct(array $elements = array()) { $this->elements = $elements; $this->orderedKeys = array_keys($elements); } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetExists($key) { return isset($this->elements[$key]); } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetGet($key) { if (!isset($this->elements[$key])) { throw new \OutOfBoundsException('The offset "' . $key . '" does not exist.'); } return $this->elements[$key]; } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetSet($key, $value) { if (null === $key || !isset($this->elements[$key])) { if (null === $key) { $key = array() === $this->orderedKeys // If the array is empty, use 0 as key ? 0 // Imitate PHP's behavior of generating a key that equals // the highest existing integer key + 1 : max($this->orderedKeys) + 1; } $this->orderedKeys[] = $key; } $this->elements[$key] = $value; } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetUnset($key) { if (false !== ($position = array_search($key, $this->orderedKeys))) { array_splice($this->orderedKeys, $position, 1); unset($this->elements[$key]); foreach ($this->managedCursors as $i => $cursor) { if ($cursor >= $position) { --$this->managedCursors[$i]; } } } } /** * {@inheritdoc} * * @since 2.2.6 */ public function getIterator() { return new OrderedHashMapIterator($this->elements, $this->orderedKeys, $this->managedCursors); } /** * {@inheritdoc} * * @since 2.2.6 */ public function count() { return count($this->elements); } } PK]y$$Form/Util/FormUtil.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * @author Bernhard Schussek */ class FormUtil { /** * This class should not be instantiated */ private function __construct() {} /** * Returns whether the given data is empty. * * This logic is reused multiple times throughout the processing of * a form and needs to be consistent. PHP's keyword `empty` cannot * be used as it also considers 0 and "0" to be empty. * * @param mixed $data * * @return Boolean */ public static function isEmpty($data) { // Should not do a check for array() === $data!!! // This method is used in occurrences where arrays are // not considered to be empty, ever. return null === $data || '' === $data; } } PK]<&Form/Util/InheritDataAwareIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * Iterator that traverses an array of forms. * * Contrary to \ArrayIterator, this iterator recognizes changes in the original * array during iteration. * * You can wrap the iterator into a {@link \RecursiveIterator} in order to * enter any child form that inherits its parent's data and iterate the children * of that form as well. * * @author Bernhard Schussek */ class InheritDataAwareIterator extends VirtualFormAwareIterator { } PK]h''$Form/Util/OrderedHashMapIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * Iterator for {@link OrderedHashMap} objects. * * This class is internal and should not be used. * * @author Bernhard Schussek * * @since 2.2.6 */ class OrderedHashMapIterator implements \Iterator { /** * @var array */ private $elements; /** * @var array */ private $orderedKeys; /** * @var integer */ private $cursor; /** * @var integer */ private $cursorId; /** * @var array */ private $managedCursors; /** * @var string|integer|null */ private $key; /** * @var mixed */ private $current; /** * Creates a new iterator. * * @param array $elements The elements of the map, indexed by their * keys. * @param array $orderedKeys The keys of the map in the order in which * they should be iterated. * @param array $managedCursors An array from which to reference the * iterator's cursor as long as it is alive. * This array is managed by the corresponding * {@link OrderedHashMap} instance to support * recognizing the deletion of elements. * * @since 2.2.6 */ public function __construct(array &$elements, array &$orderedKeys, array &$managedCursors) { $this->elements = &$elements; $this->orderedKeys = &$orderedKeys; $this->managedCursors = &$managedCursors; $this->cursorId = count($managedCursors); $this->managedCursors[$this->cursorId] = &$this->cursor; } /** * Removes the iterator's cursors from the managed cursors of the * corresponding {@link OrderedHashMap} instance. * * @since 2.2.6 */ public function __destruct() { // Use array_splice() instead of isset() to prevent holes in the // array indices, which would break the initialization of $cursorId array_splice($this->managedCursors, $this->cursorId, 1); } /** *{@inheritdoc} * * @since 2.2.6 */ public function current() { return $this->current; } /** * {@inheritdoc} * * @since 2.2.6 */ public function next() { ++$this->cursor; if (isset($this->orderedKeys[$this->cursor])) { $this->key = $this->orderedKeys[$this->cursor]; $this->current = $this->elements[$this->key]; } else { $this->key = null; $this->current = null; } } /** *{@inheritdoc} * * @since 2.2.6 */ public function key() { return $this->key; } /** *{@inheritdoc} * * @since 2.2.6 */ public function valid() { return null !== $this->key; } /** *{@inheritdoc} * * @since 2.2.6 */ public function rewind() { $this->cursor = 0; if (isset($this->orderedKeys[0])) { $this->key = $this->orderedKeys[0]; $this->current = $this->elements[$this->key]; } else { $this->key = null; $this->current = null; } } } PK]|G "Form/ResolvedFormTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A wrapper for a form type and its extensions. * * @author Bernhard Schussek */ interface ResolvedFormTypeInterface { /** * Returns the name of the type. * * @return string The type name. */ public function getName(); /** * Returns the parent type. * * @return ResolvedFormTypeInterface|null The parent type or null. */ public function getParent(); /** * Returns the wrapped form type. * * @return FormTypeInterface The wrapped form type. */ public function getInnerType(); /** * Returns the extensions of the wrapped form type. * * @return FormTypeExtensionInterface[] An array of {@link FormTypeExtensionInterface} instances. */ public function getTypeExtensions(); /** * Creates a new form builder for this type. * * @param FormFactoryInterface $factory The form factory. * @param string $name The name for the builder. * @param array $options The builder options. * * @return FormBuilderInterface The created form builder. */ public function createBuilder(FormFactoryInterface $factory, $name, array $options = array()); /** * Creates a new form view for a form of this type. * * @param FormInterface $form The form to create a view for. * @param FormView $parent The parent view or null. * * @return FormView The created form view. */ public function createView(FormInterface $form, FormView $parent = null); /** * Configures a form builder for the type hierarchy. * * @param FormBuilderInterface $builder The builder to configure. * @param array $options The options used for the configuration. */ public function buildForm(FormBuilderInterface $builder, array $options); /** * Configures a form view for the type hierarchy. * * It is called before the children of the view are built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function buildView(FormView $view, FormInterface $form, array $options); /** * Finishes a form view for the type hierarchy. * * It is called after the children of the view have been built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function finishView(FormView $view, FormInterface $form, array $options); /** * Returns the configured options resolver used for this type. * * @return \Symfony\Component\OptionsResolver\OptionsResolverInterface The options resolver. */ public function getOptionsResolver(); } PK]nForm/FormExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Interface for extensions which provide types, type extensions and a guesser. */ interface FormExtensionInterface { /** * Returns a type by name. * * @param string $name The name of the type * * @return FormTypeInterface The type * * @throws Exception\InvalidArgumentException if the given type is not supported by this extension */ public function getType($name); /** * Returns whether the given type is supported. * * @param string $name The name of the type * * @return Boolean Whether the type is supported by this extension */ public function hasType($name); /** * Returns the extensions for the given type. * * @param string $name The name of the type * * @return FormTypeExtensionInterface[] An array of extensions as FormTypeExtensionInterface instances */ public function getTypeExtensions($name); /** * Returns whether this extension provides type extensions for the given type. * * @param string $name The name of the type * * @return Boolean Whether the given type has extensions */ public function hasTypeExtensions($name); /** * Returns the type guesser provided by this extension. * * @return FormTypeGuesserInterface|null The type guesser */ public function getTypeGuesser(); } PK]Wb[H[HForm/ButtonBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\BadMethodCallException; /** * A builder for {@link Button} instances. * * @author Bernhard Schussek */ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface { /** * @var Boolean */ protected $locked = false; /** * @var Boolean */ private $disabled; /** * @var ResolvedFormTypeInterface */ private $type; /** * @var string */ private $name; /** * @var array */ private $attributes = array(); /** * @var array */ private $options; /** * Creates a new button builder. * * @param string $name The name of the button. * @param array $options The button's options. * * @throws InvalidArgumentException If the name is empty. */ public function __construct($name, array $options = array()) { if (empty($name) && 0 != $name) { throw new InvalidArgumentException('Buttons cannot have empty names.'); } $this->name = (string) $name; $this->options = $options; } /** * Unsupported method. * * This method should not be invoked. * * @param string|integer|FormBuilderInterface $child * @param string|FormTypeInterface $type * @param array $options * * @throws BadMethodCallException */ public function add($child, $type = null, array $options = array()) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * @param string|FormTypeInterface $type * @param array $options * * @throws BadMethodCallException */ public function create($name, $type = null, array $options = array()) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function get($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function remove($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * @param string $name * * @return Boolean Always returns false. */ public function has($name) { return false; } /** * Returns the children. * * @return array Always returns an empty array. */ public function all() { return array(); } /** * Creates the button. * * @return Button The button */ public function getForm() { return new Button($this->getFormConfig()); } /** * Unsupported method. * * This method should not be invoked. * * @param string $eventName * @param callable $listener * @param integer $priority * * @throws BadMethodCallException */ public function addEventListener($eventName, $listener, $priority = 0) { throw new BadMethodCallException('Buttons do not support event listeners.'); } /** * Unsupported method. * * This method should not be invoked. * * @param EventSubscriberInterface $subscriber * * @throws BadMethodCallException */ public function addEventSubscriber(EventSubscriberInterface $subscriber) { throw new BadMethodCallException('Buttons do not support event subscribers.'); } /** * Unsupported method. * * This method should not be invoked. * * @param DataTransformerInterface $viewTransformer * @param Boolean $forcePrepend * * @throws BadMethodCallException */ public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false) { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * Unsupported method. * * This method should not be invoked. * * @throws BadMethodCallException */ public function resetViewTransformers() { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * Unsupported method. * * This method should not be invoked. * * @param DataTransformerInterface $modelTransformer * @param Boolean $forceAppend * * @throws BadMethodCallException */ public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false) { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * Unsupported method. * * This method should not be invoked. * * @throws BadMethodCallException */ public function resetModelTransformers() { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * {@inheritdoc} */ public function setAttribute($name, $value) { $this->attributes[$name] = $value; } /** * {@inheritdoc} */ public function setAttributes(array $attributes) { $this->attributes = $attributes; } /** * Unsupported method. * * This method should not be invoked. * * @param DataMapperInterface $dataMapper * * @throws BadMethodCallException */ public function setDataMapper(DataMapperInterface $dataMapper = null) { throw new BadMethodCallException('Buttons do not support data mappers.'); } /** * Set whether the button is disabled. * * @param Boolean $disabled Whether the button is disabled * * @return ButtonBuilder The button builder. */ public function setDisabled($disabled) { $this->disabled = $disabled; } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $emptyData * * @throws BadMethodCallException */ public function setEmptyData($emptyData) { throw new BadMethodCallException('Buttons do not support empty data.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $errorBubbling * * @throws BadMethodCallException */ public function setErrorBubbling($errorBubbling) { throw new BadMethodCallException('Buttons do not support error bubbling.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $required * * @throws BadMethodCallException */ public function setRequired($required) { throw new BadMethodCallException('Buttons cannot be required.'); } /** * Unsupported method. * * This method should not be invoked. * * @param null $propertyPath * * @throws BadMethodCallException */ public function setPropertyPath($propertyPath) { throw new BadMethodCallException('Buttons do not support property paths.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $mapped * * @throws BadMethodCallException */ public function setMapped($mapped) { throw new BadMethodCallException('Buttons do not support data mapping.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $byReference * * @throws BadMethodCallException */ public function setByReference($byReference) { throw new BadMethodCallException('Buttons do not support data mapping.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $virtual * * @throws BadMethodCallException */ public function setVirtual($virtual) { throw new BadMethodCallException('Buttons cannot be virtual.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $compound * * @throws BadMethodCallException */ public function setCompound($compound) { throw new BadMethodCallException('Buttons cannot be compound.'); } /** * Sets the type of the button. * * @param ResolvedFormTypeInterface $type The type of the button. * * @return ButtonBuilder The button builder. */ public function setType(ResolvedFormTypeInterface $type) { $this->type = $type; } /** * Unsupported method. * * This method should not be invoked. * * @param array $data * * @throws BadMethodCallException */ public function setData($data) { throw new BadMethodCallException('Buttons do not support data.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $locked * * @throws BadMethodCallException */ public function setDataLocked($locked) { throw new BadMethodCallException('Buttons do not support data locking.'); } /** * Unsupported method. * * This method should not be invoked. * * @param FormFactoryInterface $formFactory * * @return void * * @throws BadMethodCallException */ public function setFormFactory(FormFactoryInterface $formFactory) { throw new BadMethodCallException('Buttons do not support form factories.'); } /** * Unsupported method. * * @param string $action * * @throws BadMethodCallException */ public function setAction($action) { throw new BadMethodCallException('Buttons do not support actions.'); } /** * Unsupported method. * * @param string $method * * @throws BadMethodCallException */ public function setMethod($method) { throw new BadMethodCallException('Buttons do not support methods.'); } /** * Unsupported method. * * @param RequestHandlerInterface $requestHandler * * @throws BadMethodCallException */ public function setRequestHandler(RequestHandlerInterface $requestHandler) { throw new BadMethodCallException('Buttons do not support form processors.'); } /** * Unsupported method. * * @param Boolean $initialize * * @throws BadMethodCallException */ public function setAutoInitialize($initialize) { if (true === $initialize) { throw new BadMethodCallException('Buttons do not support automatic initialization.'); } return $this; } /** * Unsupported method. * * @param Boolean $inheritData * * @throws BadMethodCallException */ public function setInheritData($inheritData) { throw new BadMethodCallException('Buttons do not support data inheritance.'); } /** * Builds and returns the button configuration. * * @return FormConfigInterface */ public function getFormConfig() { // This method should be idempotent, so clone the builder $config = clone $this; $config->locked = true; return $config; } /** * Unsupported method. * * @return null Always returns null. */ public function getEventDispatcher() { return null; } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * Unsupported method. * * @return null Always returns null. */ public function getPropertyPath() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getMapped() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getByReference() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getVirtual() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getCompound() { return false; } /** * Returns the form type used to construct the button. * * @return ResolvedFormTypeInterface The button's type. */ public function getType() { return $this->type; } /** * Unsupported method. * * @return array Always returns an empty array. */ public function getViewTransformers() { return array(); } /** * Unsupported method. * * @return array Always returns an empty array. */ public function getModelTransformers() { return array(); } /** * Unsupported method. * * @return null Always returns null. */ public function getDataMapper() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getRequired() { return false; } /** * Returns whether the button is disabled. * * @return Boolean Whether the button is disabled. */ public function getDisabled() { return $this->disabled; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getErrorBubbling() { return false; } /** * Unsupported method. * * @return null Always returns null. */ public function getEmptyData() { return null; } /** * Returns additional attributes of the button. * * @return array An array of key-value combinations. */ public function getAttributes() { return $this->attributes; } /** * Returns whether the attribute with the given name exists. * * @param string $name The attribute name. * * @return Boolean Whether the attribute exists. */ public function hasAttribute($name) { return array_key_exists($name, $this->attributes); } /** * Returns the value of the given attribute. * * @param string $name The attribute name. * @param mixed $default The value returned if the attribute does not exist. * * @return mixed The attribute value. */ public function getAttribute($name, $default = null) { return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** * Unsupported method. * * @return null Always returns null. */ public function getData() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getDataClass() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getDataLocked() { return false; } /** * Unsupported method. * * @return null Always returns null. */ public function getFormFactory() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getAction() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getMethod() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getRequestHandler() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getAutoInitialize() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getInheritData() { return false; } /** * Returns all options passed during the construction of the button. * * @return array The passed options. */ public function getOptions() { return $this->options; } /** * Returns whether a specific option exists. * * @param string $name The option name, * * @return Boolean Whether the option exists. */ public function hasOption($name) { return array_key_exists($name, $this->options); } /** * Returns the value of a specific option. * * @param string $name The option name. * @param mixed $default The value returned if the option does not exist. * * @return mixed The option value. */ public function getOption($name, $default = null) { return array_key_exists($name, $this->options) ? $this->options[$name] : $default; } /** * Unsupported method. * * @return integer Always returns 0. */ public function count() { return 0; } /** * Unsupported method. * * @return \EmptyIterator Always returns an empty iterator. */ public function getIterator() { return new \EmptyIterator(); } } PK]/ttForm/FormEvents.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ final class FormEvents { const PRE_SUBMIT = 'form.pre_bind'; const SUBMIT = 'form.bind'; const POST_SUBMIT = 'form.post_bind'; const PRE_SET_DATA = 'form.pre_set_data'; const POST_SET_DATA = 'form.post_set_data'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link PRE_SUBMIT} instead. */ const PRE_BIND = 'form.pre_bind'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link SUBMIT} instead. */ const BIND = 'form.bind'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link POST_SUBMIT} instead. */ const POST_BIND = 'form.post_bind'; private function __construct() { } } PK]  Form/Guess/TypeGuess.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Guess; /** * Contains a guessed class name and a list of options for creating an instance * of that class * * @author Bernhard Schussek */ class TypeGuess extends Guess { /** * The guessed field type * @var string */ private $type; /** * The guessed options for creating an instance of the guessed class * @var array */ private $options; /** * Constructor * * @param string $type The guessed field type * @param array $options The options for creating instances of the * guessed class * @param integer $confidence The confidence that the guessed class name * is correct */ public function __construct($type, array $options, $confidence) { parent::__construct($confidence); $this->type = $type; $this->options = $options; } /** * Returns the guessed field type * * @return string */ public function getType() { return $this->type; } /** * Returns the guessed options for creating instances of the guessed type * * @return array */ public function getOptions() { return $this->options; } } PK]RForm/Guess/ValueGuess.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Guess; /** * Contains a guessed value * * @author Bernhard Schussek */ class ValueGuess extends Guess { /** * The guessed value * @var array */ private $value; /** * Constructor * * @param string $value The guessed value * @param integer $confidence The confidence that the guessed class name * is correct */ public function __construct($value, $confidence) { parent::__construct($confidence); $this->value = $value; } /** * Returns the guessed value * * @return mixed */ public function getValue() { return $this->value; } } PK]51 1 Form/Guess/Guess.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Guess; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * Base class for guesses made by TypeGuesserInterface implementation * * Each instance contains a confidence value about the correctness of the guess. * Thus an instance with confidence HIGH_CONFIDENCE is more likely to be * correct than an instance with confidence LOW_CONFIDENCE. * * @author Bernhard Schussek */ abstract class Guess { /** * Marks an instance with a value that is extremely likely to be correct * @var integer */ const VERY_HIGH_CONFIDENCE = 3; /** * Marks an instance with a value that is very likely to be correct * @var integer */ const HIGH_CONFIDENCE = 2; /** * Marks an instance with a value that is likely to be correct * @var integer */ const MEDIUM_CONFIDENCE = 1; /** * Marks an instance with a value that may be correct * @var integer */ const LOW_CONFIDENCE = 0; /** * The confidence about the correctness of the value * * One of VERY_HIGH_CONFIDENCE, HIGH_CONFIDENCE, MEDIUM_CONFIDENCE * and LOW_CONFIDENCE. * * @var integer */ private $confidence; /** * Returns the guess most likely to be correct from a list of guesses. * * If there are multiple guesses with the same, highest confidence, the * returned guess is any of them. * * @param Guess[] $guesses An array of guesses * * @return Guess|null The guess with the highest confidence */ public static function getBestGuess(array $guesses) { $result = null; $maxConfidence = -1; foreach ($guesses as $guess) { if ($maxConfidence < $confidence = $guess->getConfidence()) { $maxConfidence = $confidence; $result = $guess; } } return $result; } /** * Constructor. * * @param integer $confidence The confidence * * @throws InvalidArgumentException if the given value of confidence is unknown */ public function __construct($confidence) { if (self::VERY_HIGH_CONFIDENCE !== $confidence && self::HIGH_CONFIDENCE !== $confidence && self::MEDIUM_CONFIDENCE !== $confidence && self::LOW_CONFIDENCE !== $confidence) { throw new InvalidArgumentException('The confidence should be one of the constants defined in Guess.'); } $this->confidence = $confidence; } /** * Returns the confidence that the guessed value is correct. * * @return integer One of the constants VERY_HIGH_CONFIDENCE, * HIGH_CONFIDENCE, MEDIUM_CONFIDENCE and LOW_CONFIDENCE */ public function getConfidence() { return $this->confidence; } } PK]pForm/AbstractRendererEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Default implementation of {@link FormRendererEngineInterface}. * * @author Bernhard Schussek */ abstract class AbstractRendererEngine implements FormRendererEngineInterface { /** * The variable in {@link FormView} used as cache key. */ const CACHE_KEY_VAR = 'cache_key'; /** * @var array */ protected $defaultThemes; /** * @var array */ protected $themes = array(); /** * @var array */ protected $resources = array(); /** * @var array */ private $resourceHierarchyLevels = array(); /** * Creates a new renderer engine. * * @param array $defaultThemes The default themes. The type of these * themes is open to the implementation. */ public function __construct(array $defaultThemes = array()) { $this->defaultThemes = $defaultThemes; } /** * {@inheritdoc} */ public function setTheme(FormView $view, $themes) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; // Do not cast, as casting turns objects into arrays of properties $this->themes[$cacheKey] = is_array($themes) ? $themes : array($themes); // Unset instead of resetting to an empty array, in order to allow // implementations (like TwigRendererEngine) to check whether $cacheKey // is set at all. unset($this->resources[$cacheKey]); unset($this->resourceHierarchyLevels[$cacheKey]); } /** * {@inheritdoc} */ public function getResourceForBlockName(FormView $view, $blockName) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; if (!isset($this->resources[$cacheKey][$blockName])) { $this->loadResourceForBlockName($cacheKey, $view, $blockName); } return $this->resources[$cacheKey][$blockName]; } /** * {@inheritdoc} */ public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchy, $hierarchyLevel) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; $blockName = $blockNameHierarchy[$hierarchyLevel]; if (!isset($this->resources[$cacheKey][$blockName])) { $this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel); } return $this->resources[$cacheKey][$blockName]; } /** * {@inheritdoc} */ public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, $hierarchyLevel) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; $blockName = $blockNameHierarchy[$hierarchyLevel]; if (!isset($this->resources[$cacheKey][$blockName])) { $this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel); } // If $block was previously rendered loaded with loadTemplateForBlock(), the template // is cached but the hierarchy level is not. In this case, we know that the block // exists at this very hierarchy level, so we can just set it. if (!isset($this->resourceHierarchyLevels[$cacheKey][$blockName])) { $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel; } return $this->resourceHierarchyLevels[$cacheKey][$blockName]; } /** * Loads the cache with the resource for a given block name. * * @see getResourceForBlock() * * @param string $cacheKey The cache key of the form view. * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * * @return Boolean True if the resource could be loaded, false otherwise. */ abstract protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName); /** * Loads the cache with the resource for a specific level of a block hierarchy. * * @see getResourceForBlockHierarchy() * * @param string $cacheKey The cache key used for storing the * resource. * @param FormView $view The form view for finding the applying * themes. * @param array $blockNameHierarchy The block hierarchy, with the most * specific block name at the end. * @param integer $hierarchyLevel The level in the block hierarchy that * should be loaded. * * @return Boolean True if the resource could be loaded, false otherwise. */ private function loadResourceForBlockNameHierarchy($cacheKey, FormView $view, array $blockNameHierarchy, $hierarchyLevel) { $blockName = $blockNameHierarchy[$hierarchyLevel]; // Try to find a template for that block if ($this->loadResourceForBlockName($cacheKey, $view, $blockName)) { // If loadTemplateForBlock() returns true, it was able to populate the // cache. The only missing thing is to set the hierarchy level at which // the template was found. $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel; return true; } if ($hierarchyLevel > 0) { $parentLevel = $hierarchyLevel - 1; $parentBlockName = $blockNameHierarchy[$parentLevel]; // The next two if statements contain slightly duplicated code. This is by intention // and tries to avoid execution of unnecessary checks in order to increase performance. if (isset($this->resources[$cacheKey][$parentBlockName])) { // It may happen that the parent block is already loaded, but its level is not. // In this case, the parent block must have been loaded by loadResourceForBlock(), // which does not check the hierarchy of the block. Subsequently the block must have // been found directly on the parent level. if (!isset($this->resourceHierarchyLevels[$cacheKey][$parentBlockName])) { $this->resourceHierarchyLevels[$cacheKey][$parentBlockName] = $parentLevel; } // Cache the shortcuts for further accesses $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName]; $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName]; return true; } if ($this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $parentLevel)) { // Cache the shortcuts for further accesses $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName]; $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName]; return true; } } // Cache the result for further accesses $this->resources[$cacheKey][$blockName] = false; $this->resourceHierarchyLevels[$cacheKey][$blockName] = false; return false; } } PK]@ @ Form/FormTypeGuesserChain.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Exception\UnexpectedTypeException; class FormTypeGuesserChain implements FormTypeGuesserInterface { private $guessers = array(); /** * Constructor. * * @param FormTypeGuesserInterface[] $guessers Guessers as instances of FormTypeGuesserInterface * * @throws UnexpectedTypeException if any guesser does not implement FormTypeGuesserInterface */ public function __construct(array $guessers) { foreach ($guessers as $guesser) { if (!$guesser instanceof FormTypeGuesserInterface) { throw new UnexpectedTypeException($guesser, 'Symfony\Component\Form\FormTypeGuesserInterface'); } if ($guesser instanceof self) { $this->guessers = array_merge($this->guessers, $guesser->guessers); } else { $this->guessers[] = $guesser; } } } /** * {@inheritDoc} */ public function guessType($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessType($class, $property); }); } /** * {@inheritDoc} */ public function guessRequired($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessRequired($class, $property); }); } /** * {@inheritDoc} */ public function guessMaxLength($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessMaxLength($class, $property); }); } /** * {@inheritDoc} */ public function guessPattern($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessPattern($class, $property); }); } /** * Executes a closure for each guesser and returns the best guess from the * return values * * @param \Closure $closure The closure to execute. Accepts a guesser * as argument and should return a Guess instance * * @return Guess|null The guess with the highest confidence */ private function guess(\Closure $closure) { $guesses = array(); foreach ($this->guessers as $guesser) { if ($guess = $closure($guesser)) { $guesses[] = $guess; } } return Guess::getBestGuess($guesses); } } PK]=MM#Form/FormTypeExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ interface FormTypeExtensionInterface { /** * Builds the form. * * This method is called after the extended type has built the form to * further modify it. * * @see FormTypeInterface::buildForm() * * @param FormBuilderInterface $builder The form builder * @param array $options The options */ public function buildForm(FormBuilderInterface $builder, array $options); /** * Builds the view. * * This method is called after the extended type has built the view to * further modify it. * * @see FormTypeInterface::buildView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function buildView(FormView $view, FormInterface $form, array $options); /** * Finishes the view. * * This method is called after the extended type has finished the view to * further modify it. * * @see FormTypeInterface::finishView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function finishView(FormView $view, FormInterface $form, array $options); /** * Overrides the default options from the extended type. * * @param OptionsResolverInterface $resolver The resolver for the options. */ public function setDefaultOptions(OptionsResolverInterface $resolver); /** * Returns the name of the type being extended. * * @return string The name of the type being extended */ public function getExtendedType(); } PK]0\ZZForm/CallbackTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\TransformationFailedException; class CallbackTransformer implements DataTransformerInterface { /** * The callback used for forward transform * @var \Closure */ private $transform; /** * The callback used for reverse transform * @var \Closure */ private $reverseTransform; /** * Constructor. * * @param \Closure $transform The forward transform callback * @param \Closure $reverseTransform The reverse transform callback */ public function __construct(\Closure $transform, \Closure $reverseTransform) { $this->transform = $transform; $this->reverseTransform = $reverseTransform; } /** * Transforms a value from the original representation to a transformed representation. * * @param mixed $data The value in the original representation * * @return mixed The value in the transformed representation * * @throws UnexpectedTypeException when the argument is not a string * @throws TransformationFailedException when the transformation fails */ public function transform($data) { return call_user_func($this->transform, $data); } /** * Transforms a value from the transformed representation to its original * representation. * * @param mixed $data The value in the transformed representation * * @return mixed The value in the original representation * * @throws UnexpectedTypeException when the argument is not of the expected type * @throws TransformationFailedException when the transformation fails */ public function reverseTransform($data) { return call_user_func($this->reverseTransform, $data); } } PK]?zz!Form/FormTypeGuesserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface FormTypeGuesserInterface { /** * Returns a field guess for a property name of a class * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\TypeGuess|null A guess for the field's type and options */ public function guessType($class, $property); /** * Returns a guess whether a property of a class is required * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\ValueGuess A guess for the field's required setting */ public function guessRequired($class, $property); /** * Returns a guess about the field's maximum length * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\ValueGuess|null A guess for the field's maximum length */ public function guessMaxLength($class, $property); /** * Returns a guess about the field's pattern * * - When you have a min value, you guess a min length of this min (LOW_CONFIDENCE) , lines below * - If this value is a float type, this is wrong so you guess null with MEDIUM_CONFIDENCE to override the previous guess. * Example: * You want a float greater than 5, 4.512313 is not valid but length(4.512314) > length(5) * @link https://github.com/symfony/symfony/pull/3927 * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\ValueGuess|null A guess for the field's required pattern */ public function guessPattern($class, $property); } PK]f#jK$Form/FormRendererEngineInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Adapter for rendering form templates with a specific templating engine. * * @author Bernhard Schussek */ interface FormRendererEngineInterface { /** * Sets the theme(s) to be used for rendering a view and its children. * * @param FormView $view The view to assign the theme(s) to. * @param mixed $themes The theme(s). The type of these themes * is open to the implementation. */ public function setTheme(FormView $view, $themes); /** * Returns the resource for a block name. * * The resource is first searched in the themes attached to $view, then * in the themes of its parent view and so on, until a resource was found. * * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * * @param FormView $view The view for determining the used themes. * First the themes attached directly to the * view with {@link setTheme()} are considered, * then the ones of its parent etc. * @param string $blockName The name of the block to render. * * @return mixed The renderer resource or false, if none was found. */ public function getResourceForBlockName(FormView $view, $blockName); /** * Returns the resource for a block hierarchy. * * A block hierarchy is an array which starts with the root of the hierarchy * and continues with the child of that root, the child of that child etc. * The following is an example for a block hierarchy: * * * form_widget * text_widget * url_widget * * * In this example, "url_widget" is the most specific block, while the other * blocks are its ancestors in the hierarchy. * * The second parameter $hierarchyLevel determines the level of the hierarchy * that should be rendered. For example, if $hierarchyLevel is 2 for the * above hierarchy, the engine will first look for the block "url_widget", * then, if that does not exist, for the block "text_widget" etc. * * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * * @param FormView $view The view for determining the * used themes. First the themes * attached directly to the view * with {@link setTheme()} are * considered, then the ones of * its parent etc. * @param array $blockNameHierarchy The block name hierarchy, with * the root block at the beginning. * @param integer $hierarchyLevel The level in the hierarchy at * which to start looking. Level 0 * indicates the root block, i.e. * the first element of * $blockNameHierarchy. * * @return mixed The renderer resource or false, if none was found. */ public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchy, $hierarchyLevel); /** * Returns the hierarchy level at which a resource can be found. * * A block hierarchy is an array which starts with the root of the hierarchy * and continues with the child of that root, the child of that child etc. * The following is an example for a block hierarchy: * * * form_widget * text_widget * url_widget * * * The second parameter $hierarchyLevel determines the level of the hierarchy * that should be rendered. * * If we call this method with the hierarchy level 2, the engine will first * look for a resource for block "url_widget". If such a resource exists, * the method returns 2. Otherwise it tries to find a resource for block * "text_widget" (at level 1) and, again, returns 1 if a resource was found. * The method continues to look for resources until the root level was * reached and nothing was found. In this case false is returned. * * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * * @param FormView $view The view for determining the * used themes. First the themes * attached directly to the view * with {@link setTheme()} are * considered, then the ones of * its parent etc. * @param array $blockNameHierarchy The block name hierarchy, with * the root block at the beginning. * @param integer $hierarchyLevel The level in the hierarchy at * which to start looking. Level 0 * indicates the root block, i.e. * the first element of * $blockNameHierarchy. * * @return integer|Boolean The hierarchy level or false, if no resource was found. */ public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, $hierarchyLevel); /** * Renders a block in the given renderer resource. * * The resource can be obtained by calling {@link getResourceForBlock()} * or {@link getResourceForBlockHierarchy()}. The type of the resource is * decided by the implementation. * * @param FormView $view The view to render. * @param mixed $resource The renderer resource. * @param string $blockName The name of the block to render. * @param array $variables The variables to pass to the template. * * @return string The HTML markup. */ public function renderBlock(FormView $view, $resource, $blockName, array $variables = array()); } PK]2Form/FormFactoryBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * The default implementation of FormFactoryBuilderInterface. * * @author Bernhard Schussek */ class FormFactoryBuilder implements FormFactoryBuilderInterface { /** * @var ResolvedFormTypeFactoryInterface */ private $resolvedTypeFactory; /** * @var array */ private $extensions = array(); /** * @var array */ private $types = array(); /** * @var array */ private $typeExtensions = array(); /** * @var array */ private $typeGuessers = array(); /** * {@inheritdoc} */ public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory) { $this->resolvedTypeFactory = $resolvedTypeFactory; return $this; } /** * {@inheritdoc} */ public function addExtension(FormExtensionInterface $extension) { $this->extensions[] = $extension; return $this; } /** * {@inheritdoc} */ public function addExtensions(array $extensions) { $this->extensions = array_merge($this->extensions, $extensions); return $this; } /** * {@inheritdoc} */ public function addType(FormTypeInterface $type) { $this->types[$type->getName()] = $type; return $this; } /** * {@inheritdoc} */ public function addTypes(array $types) { foreach ($types as $type) { $this->types[$type->getName()] = $type; } return $this; } /** * {@inheritdoc} */ public function addTypeExtension(FormTypeExtensionInterface $typeExtension) { $this->typeExtensions[$typeExtension->getExtendedType()][] = $typeExtension; return $this; } /** * {@inheritdoc} */ public function addTypeExtensions(array $typeExtensions) { foreach ($typeExtensions as $typeExtension) { $this->typeExtensions[$typeExtension->getExtendedType()][] = $typeExtension; } return $this; } /** * {@inheritdoc} */ public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser) { $this->typeGuessers[] = $typeGuesser; return $this; } /** * {@inheritdoc} */ public function addTypeGuessers(array $typeGuessers) { $this->typeGuessers = array_merge($this->typeGuessers, $typeGuessers); return $this; } /** * {@inheritdoc} */ public function getFormFactory() { $extensions = $this->extensions; if (count($this->types) > 0 || count($this->typeExtensions) > 0 || count($this->typeGuessers) > 0) { if (count($this->typeGuessers) > 1) { $typeGuesser = new FormTypeGuesserChain($this->typeGuessers); } else { $typeGuesser = isset($this->typeGuessers[0]) ? $this->typeGuessers[0] : null; } $extensions[] = new PreloadedExtension($this->types, $this->typeExtensions, $typeGuesser); } $resolvedTypeFactory = $this->resolvedTypeFactory ?: new ResolvedFormTypeFactory(); $registry = new FormRegistry($extensions, $resolvedTypeFactory); return new FormFactory($registry, $resolvedTypeFactory); } } PK]E1'"Form/SubmitButtonTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A type that should be converted into a {@link SubmitButton} instance. * * @author Bernhard Schussek */ interface SubmitButtonTypeInterface extends FormTypeInterface { } PK]K'$Form/FormBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * A builder for creating {@link Form} instances. * * @author Bernhard Schussek */ class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormBuilderInterface { /** * The children of the form builder. * * @var FormBuilderInterface[] */ private $children = array(); /** * The data of children who haven't been converted to form builders yet. * * @var array */ private $unresolvedChildren = array(); /** * Creates a new form builder. * * @param string $name * @param string $dataClass * @param EventDispatcherInterface $dispatcher * @param FormFactoryInterface $factory * @param array $options */ public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, FormFactoryInterface $factory, array $options = array()) { parent::__construct($name, $dataClass, $dispatcher, $options); $this->setFormFactory($factory); } /** * {@inheritdoc} */ public function add($child, $type = null, array $options = array()) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($child instanceof self) { $this->children[$child->getName()] = $child; // In case an unresolved child with the same name exists unset($this->unresolvedChildren[$child->getName()]); return $this; } if (!is_string($child) && !is_int($child)) { throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormBuilder'); } if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) { throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface'); } // Add to "children" to maintain order $this->children[$child] = null; $this->unresolvedChildren[$child] = array( 'type' => $type, 'options' => $options, ); return $this; } /** * {@inheritdoc} */ public function create($name, $type = null, array $options = array()) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (null === $type && null === $this->getDataClass()) { $type = 'text'; } if (null !== $type) { return $this->getFormFactory()->createNamedBuilder($name, $type, null, $options); } return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $name, null, $options); } /** * {@inheritdoc} */ public function get($name) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (isset($this->unresolvedChildren[$name])) { return $this->resolveChild($name); } if (isset($this->children[$name])) { return $this->children[$name]; } throw new InvalidArgumentException(sprintf('The child with the name "%s" does not exist.', $name)); } /** * {@inheritdoc} */ public function remove($name) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } unset($this->unresolvedChildren[$name]); if (array_key_exists($name, $this->children)) { unset($this->children[$name]); } return $this; } /** * {@inheritdoc} */ public function has($name) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (isset($this->unresolvedChildren[$name])) { return true; } if (isset($this->children[$name])) { return true; } return false; } /** * {@inheritdoc} */ public function all() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->resolveChildren(); return $this->children; } /** * {@inheritdoc} */ public function count() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return count($this->children); } /** * {@inheritdoc} */ public function getFormConfig() { $config = parent::getFormConfig(); $config->children = array(); $config->unresolvedChildren = array(); return $config; } /** * {@inheritdoc} */ public function getForm() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->resolveChildren(); $form = new Form($this->getFormConfig()); foreach ($this->children as $child) { // Automatic initialization is only supported on root forms $form->add($child->setAutoInitialize(false)->getForm()); } if ($this->getAutoInitialize()) { // Automatically initialize the form if it is configured so $form->initialize(); } return $form; } /** * {@inheritdoc} */ public function getIterator() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return new \ArrayIterator($this->children); } /** * Converts an unresolved child into a {@link FormBuilder} instance. * * @param string $name The name of the unresolved child. * * @return FormBuilder The created instance. */ private function resolveChild($name) { $info = $this->unresolvedChildren[$name]; $child = $this->create($name, $info['type'], $info['options']); $this->children[$name] = $child; unset($this->unresolvedChildren[$name]); return $child; } /** * Converts all unresolved children into {@link FormBuilder} instances. */ private function resolveChildren() { foreach ($this->unresolvedChildren as $name => $info) { $this->children[$name] = $this->create($name, $info['type'], $info['options']); } $this->unresolvedChildren = array(); } } PK]YBForm/ReversedTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Reverses a transformer * * When the transform() method is called, the reversed transformer's * reverseTransform() method is called and vice versa. * * @author Bernhard Schussek */ class ReversedTransformer implements DataTransformerInterface { /** * The reversed transformer * @var DataTransformerInterface */ protected $reversedTransformer; /** * Reverses this transformer * * @param DataTransformerInterface $reversedTransformer */ public function __construct(DataTransformerInterface $reversedTransformer) { $this->reversedTransformer = $reversedTransformer; } /** * {@inheritDoc} */ public function transform($value) { return $this->reversedTransformer->reverseTransform($value); } /** * {@inheritDoc} */ public function reverseTransform($value) { return $this->reversedTransformer->transform($value); } } PK]}p  Form/FormError.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Wraps errors in forms * * @author Bernhard Schussek */ class FormError { /** * @var string */ private $message; /** * The template for the error message * @var string */ protected $messageTemplate; /** * The parameters that should be substituted in the message template * @var array */ protected $messageParameters; /** * The value for error message pluralization * @var integer|null */ protected $messagePluralization; /** * Constructor * * Any array key in $messageParameters will be used as a placeholder in * $messageTemplate. * * @param string $message The translated error message * @param string|null $messageTemplate The template for the error message * @param array $messageParameters The parameters that should be * substituted in the message template. * @param integer|null $messagePluralization The value for error message pluralization * * @see \Symfony\Component\Translation\Translator */ public function __construct($message, $messageTemplate = null, array $messageParameters = array(), $messagePluralization = null) { $this->message = $message; $this->messageTemplate = $messageTemplate ?: $message; $this->messageParameters = $messageParameters; $this->messagePluralization = $messagePluralization; } /** * Returns the error message * * @return string */ public function getMessage() { return $this->message; } /** * Returns the error message template * * @return string */ public function getMessageTemplate() { return $this->messageTemplate; } /** * Returns the parameters to be inserted in the message template * * @return array */ public function getMessageParameters() { return $this->messageParameters; } /** * Returns the value for error message pluralization. * * @return integer|null */ public function getMessagePluralization() { return $this->messagePluralization; } } PK]z5 Form/ResolvedFormTypeFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ class ResolvedFormTypeFactory implements ResolvedFormTypeFactoryInterface { /** * {@inheritdoc} */ public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null) { return new ResolvedFormType($type, $typeExtensions, $parent); } } PK]Z)Form/FormFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface FormFactoryInterface { /** * Returns a form. * * @see createBuilder() * * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormInterface The form named after the type * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function create($type = 'form', $data = null, array $options = array()); /** * Returns a form. * * @see createNamedBuilder() * * @param string|integer $name The name of the form * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormInterface The form * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createNamed($name, $type = 'form', $data = null, array $options = array()); /** * Returns a form for a property of a class. * * @see createBuilderForProperty() * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * @param mixed $data The initial data * @param array $options The options for the builder * * @return FormInterface The form named after the property * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the form type */ public function createForProperty($class, $property, $data = null, array $options = array()); /** * Returns a form builder. * * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormBuilderInterface The form builder * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createBuilder($type = 'form', $data = null, array $options = array()); /** * Returns a form builder. * * @param string|integer $name The name of the form * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormBuilderInterface The form builder * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array()); /** * Returns a form builder for a property of a class. * * If any of the 'max_length', 'required' and type options can be guessed, * and are not provided in the options argument, the guessed value is used. * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * @param mixed $data The initial data * @param array $options The options for the builder * * @return FormBuilderInterface The form builder named after the property * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the form type */ public function createBuilderForProperty($class, $property, $data = null, array $options = array()); } PK]X!Form/Exception/LogicException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base LogicException for Form component. * * @author Alexander Kotynia */ class LogicException extends \LogicException implements ExceptionInterface { } PK]yu%Form/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base ExceptionInterface for the Form component. * * @author Bernhard Schussek */ interface ExceptionInterface { } PK]N#Form/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base RuntimeException for the Form component. * * @author Bernhard Schussek */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK]W  (Form/Exception/AlreadyBoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Alias of {@link AlreadySubmittedException}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link AlreadySubmittedException} instead. */ class AlreadyBoundException extends LogicException { } PK]K9,Form/Exception/AlreadySubmittedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Thrown when an operation is called that is not acceptable after submitting * a form. * * @author Bernhard Schussek */ class AlreadySubmittedException extends AlreadyBoundException { } PK]1;TT(Form/Exception/ErrorMappingException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class ErrorMappingException extends RuntimeException { } PK]di)Form/Exception/BadMethodCallException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base BadMethodCallException for the Form component. * * @author Bernhard Schussek */ class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface { } PK]_c==*Form/Exception/UnexpectedTypeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class UnexpectedTypeException extends InvalidArgumentException { public function __construct($value, $expectedType) { parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value))); } } PK]+RR&Form/Exception/StringCastException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class StringCastException extends RuntimeException { } PK](dd0Form/Exception/InvalidConfigurationException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class InvalidConfigurationException extends InvalidArgumentException { } PK]gBz+Form/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base InvalidArgumentException for the Form component. * * @author Bernhard Schussek */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PK]SD0Form/Exception/TransformationFailedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Indicates a value transformation error. * * @author Bernhard Schussek */ class TransformationFailedException extends RuntimeException { } PK]é'Form/Exception/OutOfBoundsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base OutOfBoundsException for Form component. * * @author Alexander Kotynia */ class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface { } PK]R}jjForm/DataMapperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface DataMapperInterface { /** * Maps properties of some data to a list of forms. * * @param mixed $data Structured data. * @param FormInterface[] $forms A list of {@link FormInterface} instances. * * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported. */ public function mapDataToForms($data, $forms); /** * Maps the data of a list of forms into the properties of some data. * * @param FormInterface[] $forms A list of {@link FormInterface} instances. * @param mixed $data Structured data. * * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported. */ public function mapFormsToData($forms, &$data); } PK]4Nz"z"Form/Button.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\AlreadySubmittedException; use Symfony\Component\Form\Exception\BadMethodCallException; /** * A form button. * * @author Bernhard Schussek */ class Button implements \IteratorAggregate, FormInterface { /** * @var FormInterface|null */ private $parent; /** * @var FormConfigInterface */ private $config; /** * @var Boolean */ private $submitted = false; /** * Creates a new button from a form configuration. * * @param FormConfigInterface $config The button's configuration. */ public function __construct(FormConfigInterface $config) { $this->config = $config; } /** * Unsupported method. * * @param mixed $offset * * @return Boolean Always returns false. */ public function offsetExists($offset) { return false; } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $offset * * @throws BadMethodCallException */ public function offsetGet($offset) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $offset * @param mixed $value * * @throws BadMethodCallException */ public function offsetSet($offset, $value) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $offset * * @throws BadMethodCallException */ public function offsetUnset($offset) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * {@inheritdoc} */ public function setParent(FormInterface $parent = null) { $this->parent = $parent; } /** * {@inheritdoc} */ public function getParent() { return $this->parent; } /** * Unsupported method. * * This method should not be invoked. * * @param int|string|FormInterface $child * @param null $type * @param array $options * * @throws BadMethodCallException */ public function add($child, $type = null, array $options = array()) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function get($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * @param string $name * * @return Boolean Always returns false. */ public function has($name) { return false; } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function remove($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * {@inheritdoc} */ public function all() { return array(); } /** * {@inheritdoc} */ public function getErrors() { return array(); } /** * Unsupported method. * * This method should not be invoked. * * @param string $modelData * * @throws BadMethodCallException */ public function setData($modelData) { // called during initialization of the form tree // noop } /** * Unsupported method. * * @return null Always returns null. */ public function getData() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getNormData() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getViewData() { return null; } /** * Unsupported method. * * @return array Always returns an empty array. */ public function getExtraData() { return array(); } /** * Returns the button's configuration. * * @return FormConfigInterface The configuration. */ public function getConfig() { return $this->config; } /** * Returns whether the button is submitted. * * @return Boolean true if the button was submitted. */ public function isSubmitted() { return $this->submitted; } /** * Returns the name by which the button is identified in forms. * * @return string The name of the button. */ public function getName() { return $this->config->getName(); } /** * Unsupported method. * * @return null Always returns null. */ public function getPropertyPath() { return null; } /** * Unsupported method. * * @param FormError $error * * @throws BadMethodCallException */ public function addError(FormError $error) { throw new BadMethodCallException('Buttons cannot have errors.'); } /** * Unsupported method. * * @return Boolean Always returns true. */ public function isValid() { return true; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function isRequired() { return false; } /** * {@inheritdoc} */ public function isDisabled() { return $this->config->getDisabled(); } /** * Unsupported method. * * @return Boolean Always returns true. */ public function isEmpty() { return true; } /** * Unsupported method. * * @return Boolean Always returns true. */ public function isSynchronized() { return true; } /** * Unsupported method. * * @throws BadMethodCallException */ public function initialize() { throw new BadMethodCallException('Buttons cannot be initialized. Call initialize() on the root form instead.'); } /** * Unsupported method. * * @param mixed $request * * @throws BadMethodCallException */ public function handleRequest($request = null) { throw new BadMethodCallException('Buttons cannot handle requests. Call handleRequest() on the root form instead.'); } /** * Submits data to the button. * * @param null|string $submittedData The data. * @param Boolean $clearMissing Not used. * * @return Button The button instance * * @throws Exception\AlreadySubmittedException If the button has already been submitted. */ public function submit($submittedData, $clearMissing = true) { if ($this->submitted) { throw new AlreadySubmittedException('A form can only be submitted once'); } $this->submitted = true; return $this; } /** * {@inheritdoc} */ public function getRoot() { return $this->parent ? $this->parent->getRoot() : $this; } /** * {@inheritdoc} */ public function isRoot() { return null === $this->parent; } /** * {@inheritdoc} */ public function createView(FormView $parent = null) { if (null === $parent && $this->parent) { $parent = $this->parent->createView(); } $type = $this->config->getType(); $options = $this->config->getOptions(); $view = $type->createView($this, $parent); $type->buildView($view, $this, $options); $type->finishView($view, $this, $options); return $view; } /** * Unsupported method. * * @return integer Always returns 0. */ public function count() { return 0; } /** * Unsupported method. * * @return \EmptyIterator Always returns an empty iterator. */ public function getIterator() { return new \EmptyIterator(); } } PK]H Form/FormView.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; /** * @author Bernhard Schussek */ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable { /** * The variables assigned to this view. * @var array */ public $vars = array( 'value' => null, 'attr' => array(), ); /** * The parent view. * @var FormView */ public $parent; /** * The child views. * @var array */ public $children = array(); /** * Is the form attached to this renderer rendered? * * Rendering happens when either the widget or the row method was called. * Row implicitly includes widget, however certain rendering mechanisms * have to skip widget rendering when a row is rendered. * * @var Boolean */ private $rendered = false; public function __construct(FormView $parent = null) { $this->parent = $parent; } /** * Returns whether the view was already rendered. * * @return Boolean Whether this view's widget is rendered. */ public function isRendered() { $hasChildren = 0 < count($this->children); if (true === $this->rendered || !$hasChildren) { return $this->rendered; } if ($hasChildren) { foreach ($this->children as $child) { if (!$child->isRendered()) { return false; } } return $this->rendered = true; } return false; } /** * Marks the view as rendered. * * @return FormView The view object. */ public function setRendered() { $this->rendered = true; return $this; } /** * Returns a child by name (implements \ArrayAccess). * * @param string $name The child name * * @return FormView The child view */ public function offsetGet($name) { return $this->children[$name]; } /** * Returns whether the given child exists (implements \ArrayAccess). * * @param string $name The child name * * @return Boolean Whether the child view exists */ public function offsetExists($name) { return isset($this->children[$name]); } /** * Implements \ArrayAccess. * * @throws BadMethodCallException always as setting a child by name is not allowed */ public function offsetSet($name, $value) { throw new BadMethodCallException('Not supported'); } /** * Removes a child (implements \ArrayAccess). * * @param string $name The child name */ public function offsetUnset($name) { unset($this->children[$name]); } /** * Returns an iterator to iterate over children (implements \IteratorAggregate) * * @return \ArrayIterator The iterator */ public function getIterator() { return new \ArrayIterator($this->children); } /** * Implements \Countable. * * @return integer The number of children views */ public function count() { return count($this->children); } } PK]{d!!#Form/FormConfigBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * @author Bernhard Schussek */ interface FormConfigBuilderInterface extends FormConfigInterface { /** * Adds an event listener to an event on this form. * * @param string $eventName The name of the event to listen to. * @param callable $listener The listener to execute. * @param integer $priority The priority of the listener. Listeners * with a higher priority are called before * listeners with a lower priority. * * @return self The configuration object. */ public function addEventListener($eventName, $listener, $priority = 0); /** * Adds an event subscriber for events on this form. * * @param EventSubscriberInterface $subscriber The subscriber to attach. * * @return self The configuration object. */ public function addEventSubscriber(EventSubscriberInterface $subscriber); /** * Appends / prepends a transformer to the view transformer chain. * * The transform method of the transformer is used to convert data from the * normalized to the view format. * The reverseTransform method of the transformer is used to convert from the * view to the normalized format. * * @param DataTransformerInterface $viewTransformer * @param Boolean $forcePrepend if set to true, prepend instead of appending * * @return self The configuration object. */ public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false); /** * Clears the view transformers. * * @return self The configuration object. */ public function resetViewTransformers(); /** * Prepends / appends a transformer to the normalization transformer chain. * * The transform method of the transformer is used to convert data from the * model to the normalized format. * The reverseTransform method of the transformer is used to convert from the * normalized to the model format. * * @param DataTransformerInterface $modelTransformer * @param Boolean $forceAppend if set to true, append instead of prepending * * @return self The configuration object. */ public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false); /** * Clears the normalization transformers. * * @return self The configuration object. */ public function resetModelTransformers(); /** * Sets the value for an attribute. * * @param string $name The name of the attribute * @param string $value The value of the attribute * * @return self The configuration object. */ public function setAttribute($name, $value); /** * Sets the attributes. * * @param array $attributes The attributes. * * @return self The configuration object. */ public function setAttributes(array $attributes); /** * Sets the data mapper used by the form. * * @param DataMapperInterface $dataMapper * * @return self The configuration object. */ public function setDataMapper(DataMapperInterface $dataMapper = null); /** * Set whether the form is disabled. * * @param Boolean $disabled Whether the form is disabled * * @return self The configuration object. */ public function setDisabled($disabled); /** * Sets the data used for the client data when no value is submitted. * * @param mixed $emptyData The empty data. * * @return self The configuration object. */ public function setEmptyData($emptyData); /** * Sets whether errors bubble up to the parent. * * @param Boolean $errorBubbling * * @return self The configuration object. */ public function setErrorBubbling($errorBubbling); /** * Sets whether this field is required to be filled out when submitted. * * @param Boolean $required * * @return self The configuration object. */ public function setRequired($required); /** * Sets the property path that the form should be mapped to. * * @param null|string|\Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath * The property path or null if the path should be set * automatically based on the form's name. * * @return self The configuration object. */ public function setPropertyPath($propertyPath); /** * Sets whether the form should be mapped to an element of its * parent's data. * * @param Boolean $mapped Whether the form should be mapped. * * @return self The configuration object. */ public function setMapped($mapped); /** * Sets whether the form's data should be modified by reference. * * @param Boolean $byReference Whether the data should be * modified by reference. * * @return self The configuration object. */ public function setByReference($byReference); /** * Sets whether the form should read and write the data of its parent. * * @param Boolean $inheritData Whether the form should inherit its parent's data. * * @return self The configuration object. */ public function setInheritData($inheritData); /** * Sets whether the form should be compound. * * @param Boolean $compound Whether the form should be compound. * * @return self The configuration object. * * @see FormConfigInterface::getCompound() */ public function setCompound($compound); /** * Set the types. * * @param ResolvedFormTypeInterface $type The type of the form. * * @return self The configuration object. */ public function setType(ResolvedFormTypeInterface $type); /** * Sets the initial data of the form. * * @param array $data The data of the form in application format. * * @return self The configuration object. */ public function setData($data); /** * Locks the form's data to the data passed in the configuration. * * A form with locked data is restricted to the data passed in * this configuration. The data can only be modified then by * submitting the form. * * @param Boolean $locked Whether to lock the default data. * * @return self The configuration object. */ public function setDataLocked($locked); /** * Sets the form factory used for creating new forms. * * @param FormFactoryInterface $formFactory The form factory. */ public function setFormFactory(FormFactoryInterface $formFactory); /** * Sets the target URL of the form. * * @param string $action The target URL of the form. * * @return self The configuration object. */ public function setAction($action); /** * Sets the HTTP method used by the form. * * @param string $method The HTTP method of the form. * * @return self The configuration object. */ public function setMethod($method); /** * Sets the request handler used by the form. * * @param RequestHandlerInterface $requestHandler * * @return self The configuration object. */ public function setRequestHandler(RequestHandlerInterface $requestHandler); /** * Sets whether the form should be initialized automatically. * * Should be set to true only for root forms. * * @param Boolean $initialize True to initialize the form automatically, * false to suppress automatic initialization. * In the second case, you need to call * {@link FormInterface::initialize()} manually. * * @return self The configuration object. */ public function setAutoInitialize($initialize); /** * Builds and returns the form configuration. * * @return FormConfigInterface */ public function getFormConfig(); } PK]DjNForm/AbstractExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ abstract class AbstractExtension implements FormExtensionInterface { /** * The types provided by this extension * @var FormTypeInterface[] An array of FormTypeInterface */ private $types; /** * The type extensions provided by this extension * @var FormTypeExtensionInterface[] An array of FormTypeExtensionInterface */ private $typeExtensions; /** * The type guesser provided by this extension * @var FormTypeGuesserInterface */ private $typeGuesser; /** * Whether the type guesser has been loaded * @var Boolean */ private $typeGuesserLoaded = false; /** * {@inheritdoc} */ public function getType($name) { if (null === $this->types) { $this->initTypes(); } if (!isset($this->types[$name])) { throw new InvalidArgumentException(sprintf('The type "%s" can not be loaded by this extension', $name)); } return $this->types[$name]; } /** * {@inheritdoc} */ public function hasType($name) { if (null === $this->types) { $this->initTypes(); } return isset($this->types[$name]); } /** * {@inheritdoc} */ public function getTypeExtensions($name) { if (null === $this->typeExtensions) { $this->initTypeExtensions(); } return isset($this->typeExtensions[$name]) ? $this->typeExtensions[$name] : array(); } /** * {@inheritdoc} */ public function hasTypeExtensions($name) { if (null === $this->typeExtensions) { $this->initTypeExtensions(); } return isset($this->typeExtensions[$name]) && count($this->typeExtensions[$name]) > 0; } /** * {@inheritdoc} */ public function getTypeGuesser() { if (!$this->typeGuesserLoaded) { $this->initTypeGuesser(); } return $this->typeGuesser; } /** * Registers the types. * * @return FormTypeInterface[] An array of FormTypeInterface instances */ protected function loadTypes() { return array(); } /** * Registers the type extensions. * * @return FormTypeExtensionInterface[] An array of FormTypeExtensionInterface instances */ protected function loadTypeExtensions() { return array(); } /** * Registers the type guesser. * * @return FormTypeGuesserInterface|null A type guesser */ protected function loadTypeGuesser() { return null; } /** * Initializes the types. * * @throws UnexpectedTypeException if any registered type is not an instance of FormTypeInterface */ private function initTypes() { $this->types = array(); foreach ($this->loadTypes() as $type) { if (!$type instanceof FormTypeInterface) { throw new UnexpectedTypeException($type, 'Symfony\Component\Form\FormTypeInterface'); } $this->types[$type->getName()] = $type; } } /** * Initializes the type extensions. * * @throws UnexpectedTypeException if any registered type extension is not * an instance of FormTypeExtensionInterface */ private function initTypeExtensions() { $this->typeExtensions = array(); foreach ($this->loadTypeExtensions() as $extension) { if (!$extension instanceof FormTypeExtensionInterface) { throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface'); } $type = $extension->getExtendedType(); $this->typeExtensions[$type][] = $extension; } } /** * Initializes the type guesser. * * @throws UnexpectedTypeException if the type guesser is not an instance of FormTypeGuesserInterface */ private function initTypeGuesser() { $this->typeGuesserLoaded = true; $this->typeGuesser = $this->loadTypeGuesser(); if (null !== $this->typeGuesser && !$this->typeGuesser instanceof FormTypeGuesserInterface) { throw new UnexpectedTypeException($this->typeGuesser, 'Symfony\Component\Form\FormTypeGuesserInterface'); } } } PK]CForm/ButtonTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A type that should be converted into a {@link Button} instance. * * @author Bernhard Schussek */ interface ButtonTypeInterface extends FormTypeInterface { } PK]rW W !Form/DataTransformerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms a value between different representations. * * @author Bernhard Schussek */ interface DataTransformerInterface { /** * Transforms a value from the original representation to a transformed representation. * * This method is called on two occasions inside a form field: * * 1. When the form field is initialized with the data attached from the datasource (object or array). * 2. When data from a request is submitted using {@link Form::submit()} to transform the new input data * back into the renderable format. For example if you have a date field and submit '2009-10-10' * you might accept this value because its easily parsed, but the transformer still writes back * "2009/10/10" onto the form field (for further displaying or other purposes). * * This method must be able to deal with empty values. Usually this will * be NULL, but depending on your implementation other empty values are * possible as well (such as empty strings). The reasoning behind this is * that value transformers must be chainable. If the transform() method * of the first value transformer outputs NULL, the second value transformer * must be able to process that value. * * By convention, transform() should return an empty string if NULL is * passed. * * @param mixed $value The value in the original representation * * @return mixed The value in the transformed representation * * @throws TransformationFailedException When the transformation fails. */ public function transform($value); /** * Transforms a value from the transformed representation to its original * representation. * * This method is called when {@link Form::submit()} is called to transform the requests tainted data * into an acceptable format for your data processing/model layer. * * This method must be able to deal with empty values. Usually this will * be an empty string, but depending on your implementation other empty * values are possible as well (such as empty strings). The reasoning behind * this is that value transformers must be chainable. If the * reverseTransform() method of the first value transformer outputs an * empty string, the second value transformer must be able to process that * value. * * By convention, reverseTransform() should return NULL if an empty string * is passed. * * @param mixed $value The value in the transformed representation * * @return mixed The value in the original representation * * @throws TransformationFailedException When the transformation fails. */ public function reverseTransform($value); } PK]>Form/FormRegistryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * The central registry of the Form component. * * @author Bernhard Schussek */ interface FormRegistryInterface { /** * Returns a form type by name. * * This methods registers the type extensions from the form extensions. * * @param string $name The name of the type * * @return ResolvedFormTypeInterface The type * * @throws Exception\UnexpectedTypeException if the passed name is not a string * @throws Exception\InvalidArgumentException if the type can not be retrieved from any extension */ public function getType($name); /** * Returns whether the given form type is supported. * * @param string $name The name of the type * * @return Boolean Whether the type is supported */ public function hasType($name); /** * Returns the guesser responsible for guessing types. * * @return FormTypeGuesserInterface|null */ public function getTypeGuesser(); /** * Returns the extensions loaded by the framework. * * @return FormExtensionInterface[] */ public function getExtensions(); } PK]11 Form/Form.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\RuntimeException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\AlreadySubmittedException; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\OutOfBoundsException; use Symfony\Component\Form\Util\FormUtil; use Symfony\Component\Form\Util\InheritDataAwareIterator; use Symfony\Component\Form\Util\OrderedHashMap; use Symfony\Component\PropertyAccess\PropertyPath; /** * Form represents a form. * * To implement your own form fields, you need to have a thorough understanding * of the data flow within a form. A form stores its data in three different * representations: * * (1) the "model" format required by the form's object * (2) the "normalized" format for internal processing * (3) the "view" format used for display * * A date field, for example, may store a date as "Y-m-d" string (1) in the * object. To facilitate processing in the field, this value is normalized * to a DateTime object (2). In the HTML representation of your form, a * localized string (3) is presented to and modified by the user. * * In most cases, format (1) and format (2) will be the same. For example, * a checkbox field uses a Boolean value for both internal processing and * storage in the object. In these cases you simply need to set a value * transformer to convert between formats (2) and (3). You can do this by * calling addViewTransformer(). * * In some cases though it makes sense to make format (1) configurable. To * demonstrate this, let's extend our above date field to store the value * either as "Y-m-d" string or as timestamp. Internally we still want to * use a DateTime object for processing. To convert the data from string/integer * to DateTime you can set a normalization transformer by calling * addNormTransformer(). The normalized data is then converted to the displayed * data as described before. * * The conversions (1) -> (2) -> (3) use the transform methods of the transformers. * The conversions (3) -> (2) -> (1) use the reverseTransform methods of the transformers. * * @author Fabien Potencier * @author Bernhard Schussek */ class Form implements \IteratorAggregate, FormInterface { /** * The form's configuration * @var FormConfigInterface */ private $config; /** * The parent of this form * @var FormInterface */ private $parent; /** * The children of this form * @var FormInterface[] A map of FormInterface instances */ private $children; /** * The errors of this form * @var FormError[] An array of FormError instances */ private $errors = array(); /** * Whether this form was submitted * @var Boolean */ private $submitted = false; /** * The button that was used to submit the form * @var Button */ private $clickedButton; /** * The form data in model format * @var mixed */ private $modelData; /** * The form data in normalized format * @var mixed */ private $normData; /** * The form data in view format * @var mixed */ private $viewData; /** * The submitted values that don't belong to any children * @var array */ private $extraData = array(); /** * Whether the data in model, normalized and view format is * synchronized. Data may not be synchronized if transformation errors * occur. * @var Boolean */ private $synchronized = true; /** * Whether the form's data has been initialized. * * When the data is initialized with its default value, that default value * is passed through the transformer chain in order to synchronize the * model, normalized and view format for the first time. This is done * lazily in order to save performance when {@link setData()} is called * manually, making the initialization with the configured default value * superfluous. * * @var Boolean */ private $defaultDataSet = false; /** * Whether setData() is currently being called. * @var Boolean */ private $lockSetData = false; /** * Creates a new form based on the given configuration. * * @param FormConfigInterface $config The form configuration. * * @throws LogicException if a data mapper is not provided for a compound form */ public function __construct(FormConfigInterface $config) { // Compound forms always need a data mapper, otherwise calls to // `setData` and `add` will not lead to the correct population of // the child forms. if ($config->getCompound() && !$config->getDataMapper()) { throw new LogicException('Compound forms need a data mapper'); } // If the form inherits the data from its parent, it is not necessary // to call setData() with the default data. if ($config->getInheritData()) { $this->defaultDataSet = true; } $this->config = $config; $this->children = new OrderedHashMap(); } public function __clone() { $this->children = clone $this->children; foreach ($this->children as $key => $child) { $this->children[$key] = clone $child; } } /** * {@inheritdoc} */ public function getConfig() { return $this->config; } /** * {@inheritdoc} */ public function getName() { return $this->config->getName(); } /** * {@inheritdoc} */ public function getPropertyPath() { if (null !== $this->config->getPropertyPath()) { return $this->config->getPropertyPath(); } if (null === $this->getName() || '' === $this->getName()) { return null; } $parent = $this->parent; while ($parent && $parent->getConfig()->getInheritData()) { $parent = $parent->getParent(); } if ($parent && null === $parent->getConfig()->getDataClass()) { return new PropertyPath('['.$this->getName().']'); } return new PropertyPath($this->getName()); } /** * {@inheritdoc} */ public function isRequired() { if (null === $this->parent || $this->parent->isRequired()) { return $this->config->getRequired(); } return false; } /** * {@inheritDoc} */ public function isDisabled() { if (null === $this->parent || !$this->parent->isDisabled()) { return $this->config->getDisabled(); } return true; } /** * {@inheritdoc} */ public function setParent(FormInterface $parent = null) { if ($this->submitted) { throw new AlreadySubmittedException('You cannot set the parent of a submitted form'); } if (null !== $parent && '' === $this->config->getName()) { throw new LogicException('A form with an empty name cannot have a parent form.'); } $this->parent = $parent; return $this; } /** * {@inheritdoc} */ public function getParent() { return $this->parent; } /** * {@inheritdoc} */ public function getRoot() { return $this->parent ? $this->parent->getRoot() : $this; } /** * {@inheritdoc} */ public function isRoot() { return null === $this->parent; } /** * {@inheritdoc} */ public function setData($modelData) { // If the form is submitted while disabled, it is set to submitted, but the data is not // changed. In such cases (i.e. when the form is not initialized yet) don't // abort this method. if ($this->submitted && $this->defaultDataSet) { throw new AlreadySubmittedException('You cannot change the data of a submitted form.'); } // If the form inherits its parent's data, disallow data setting to // prevent merge conflicts if ($this->config->getInheritData()) { throw new RuntimeException('You cannot change the data of a form inheriting its parent data.'); } // Don't allow modifications of the configured data if the data is locked if ($this->config->getDataLocked() && $modelData !== $this->config->getData()) { return $this; } if (is_object($modelData) && !$this->config->getByReference()) { $modelData = clone $modelData; } if ($this->lockSetData) { throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead.'); } $this->lockSetData = true; $dispatcher = $this->config->getEventDispatcher(); // Hook to change content of the data if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA)) { $event = new FormEvent($this, $modelData); $dispatcher->dispatch(FormEvents::PRE_SET_DATA, $event); $modelData = $event->getData(); } // Treat data as strings unless a value transformer exists if (!$this->config->getViewTransformers() && !$this->config->getModelTransformers() && is_scalar($modelData)) { $modelData = (string) $modelData; } // Synchronize representations - must not change the content! $normData = $this->modelToNorm($modelData); $viewData = $this->normToView($normData); // Validate if view data matches data class (unless empty) if (!FormUtil::isEmpty($viewData)) { $dataClass = $this->config->getDataClass(); $actualType = is_object($viewData) ? 'an instance of class '.get_class($viewData) : ' a(n) '.gettype($viewData); if (null === $dataClass && is_object($viewData) && !$viewData instanceof \ArrayAccess) { $expectedType = 'scalar, array or an instance of \ArrayAccess'; throw new LogicException( 'The form\'s view data is expected to be of type '.$expectedType.', ' . 'but is '.$actualType.'. You ' . 'can avoid this error by setting the "data_class" option to ' . '"'.get_class($viewData).'" or by adding a view transformer ' . 'that transforms '.$actualType.' to '.$expectedType.'.' ); } if (null !== $dataClass && !$viewData instanceof $dataClass) { throw new LogicException( 'The form\'s view data is expected to be an instance of class ' . $dataClass.', but is '. $actualType.'. You can avoid this error ' . 'by setting the "data_class" option to null or by adding a view ' . 'transformer that transforms '.$actualType.' to an instance of ' . $dataClass.'.' ); } } $this->modelData = $modelData; $this->normData = $normData; $this->viewData = $viewData; $this->defaultDataSet = true; $this->lockSetData = false; // It is not necessary to invoke this method if the form doesn't have children, // even if the form is compound. if (count($this->children) > 0) { // Update child forms from the data $iterator = new InheritDataAwareIterator($this->children); $iterator = new \RecursiveIteratorIterator($iterator); $this->config->getDataMapper()->mapDataToForms($viewData, $iterator); } if ($dispatcher->hasListeners(FormEvents::POST_SET_DATA)) { $event = new FormEvent($this, $modelData); $dispatcher->dispatch(FormEvents::POST_SET_DATA, $event); } return $this; } /** * {@inheritdoc} */ public function getData() { if ($this->config->getInheritData()) { if (!$this->parent) { throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); } return $this->parent->getData(); } if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this->modelData; } /** * {@inheritdoc} */ public function getNormData() { if ($this->config->getInheritData()) { if (!$this->parent) { throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); } return $this->parent->getNormData(); } if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this->normData; } /** * {@inheritdoc} */ public function getViewData() { if ($this->config->getInheritData()) { if (!$this->parent) { throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); } return $this->parent->getViewData(); } if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this->viewData; } /** * {@inheritdoc} */ public function getExtraData() { return $this->extraData; } /** * {@inheritdoc} */ public function initialize() { if (null !== $this->parent) { throw new RuntimeException('Only root forms should be initialized.'); } // Guarantee that the *_SET_DATA events have been triggered once the // form is initialized. This makes sure that dynamically added or // removed fields are already visible after initialization. if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this; } /** * {@inheritdoc} */ public function handleRequest($request = null) { $this->config->getRequestHandler()->handleRequest($this, $request); return $this; } /** * {@inheritdoc} */ public function submit($submittedData, $clearMissing = true) { if ($this->submitted) { throw new AlreadySubmittedException('A form can only be submitted once'); } // Initialize errors in the very beginning so that we don't lose any // errors added during listeners $this->errors = array(); // Obviously, a disabled form should not change its data upon submission. if ($this->isDisabled()) { $this->submitted = true; return $this; } // The data must be initialized if it was not initialized yet. // This is necessary to guarantee that the *_SET_DATA listeners // are always invoked before submit() takes place. if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } // Treat false as NULL to support binding false to checkboxes. // Don't convert NULL to a string here in order to determine later // whether an empty value has been submitted or whether no value has // been submitted at all. This is important for processing checkboxes // and radio buttons with empty values. if (false === $submittedData) { $submittedData = null; } elseif (is_scalar($submittedData)) { $submittedData = (string) $submittedData; } $dispatcher = $this->config->getEventDispatcher(); $modelData = null; $normData = null; $viewData = null; try { // Hook to change content of the data submitted by the browser if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) { $event = new FormEvent($this, $submittedData); $dispatcher->dispatch(FormEvents::PRE_SUBMIT, $event); $submittedData = $event->getData(); } // Check whether the form is compound. // This check is preferable over checking the number of children, // since forms without children may also be compound. // (think of empty collection forms) if ($this->config->getCompound()) { if (null === $submittedData) { $submittedData = array(); } if (!is_array($submittedData)) { throw new TransformationFailedException('Compound forms expect an array or NULL on submission.'); } foreach ($this->children as $name => $child) { if (array_key_exists($name, $submittedData) || $clearMissing) { $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); unset($submittedData[$name]); if (null !== $this->clickedButton) { continue; } if ($child instanceof ClickableInterface && $child->isClicked()) { $this->clickedButton = $child; continue; } if (method_exists($child, 'getClickedButton') && null !== $child->getClickedButton()) { $this->clickedButton = $child->getClickedButton(); } } } $this->extraData = $submittedData; } // Forms that inherit their parents' data also are not processed, // because then it would be too difficult to merge the changes in // the child and the parent form. Instead, the parent form also takes // changes in the grandchildren (i.e. children of the form that inherits // its parent's data) into account. // (see InheritDataAwareIterator below) if (!$this->config->getInheritData()) { // If the form is compound, the default data in view format // is reused. The data of the children is merged into this // default data using the data mapper. // If the form is not compound, the submitted data is also the data in view format. $viewData = $this->config->getCompound() ? $this->viewData : $submittedData; if (FormUtil::isEmpty($viewData)) { $emptyData = $this->config->getEmptyData(); if ($emptyData instanceof \Closure) { /* @var \Closure $emptyData */ $emptyData = $emptyData($this, $viewData); } $viewData = $emptyData; } // Merge form data from children into existing view data // It is not necessary to invoke this method if the form has no children, // even if it is compound. if (count($this->children) > 0) { // Use InheritDataAwareIterator to process children of // descendants that inherit this form's data. // These descendants will not be submitted normally (see the check // for $this->config->getInheritData() above) $childrenIterator = new InheritDataAwareIterator($this->children); $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); $this->config->getDataMapper()->mapFormsToData($childrenIterator, $viewData); } // Normalize data to unified representation $normData = $this->viewToNorm($viewData); // Hook to change content of the data in the normalized // representation if ($dispatcher->hasListeners(FormEvents::SUBMIT)) { $event = new FormEvent($this, $normData); $dispatcher->dispatch(FormEvents::SUBMIT, $event); $normData = $event->getData(); } // Synchronize representations - must not change the content! $modelData = $this->normToModel($normData); $viewData = $this->normToView($normData); } } catch (TransformationFailedException $e) { $this->synchronized = false; // If $viewData was not yet set, set it to $submittedData so that // the erroneous data is accessible on the form. // Forms that inherit data never set any data, because the getters // forward to the parent form's getters anyway. if (null === $viewData && !$this->config->getInheritData()) { $viewData = $submittedData; } } $this->submitted = true; $this->modelData = $modelData; $this->normData = $normData; $this->viewData = $viewData; if ($dispatcher->hasListeners(FormEvents::POST_SUBMIT)) { $event = new FormEvent($this, $viewData); $dispatcher->dispatch(FormEvents::POST_SUBMIT, $event); } return $this; } /** * Alias of {@link submit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link submit()} instead. */ public function bind($submittedData) { return $this->submit($submittedData); } /** * {@inheritdoc} */ public function addError(FormError $error) { if ($this->parent && $this->config->getErrorBubbling()) { $this->parent->addError($error); } else { $this->errors[] = $error; } return $this; } /** * {@inheritdoc} */ public function isSubmitted() { return $this->submitted; } /** * Alias of {@link isSubmitted()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link isSubmitted()} instead. */ public function isBound() { return $this->submitted; } /** * {@inheritdoc} */ public function isSynchronized() { return $this->synchronized; } /** * {@inheritdoc} */ public function isEmpty() { foreach ($this->children as $child) { if (!$child->isEmpty()) { return false; } } return FormUtil::isEmpty($this->modelData) || // arrays, countables 0 === count($this->modelData) || // traversables that are not countable ($this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData)); } /** * {@inheritdoc} */ public function isValid() { if (!$this->submitted) { return false; } if (count($this->errors) > 0) { return false; } if ($this->isDisabled()) { return true; } foreach ($this->children as $child) { if ($child->isSubmitted() && !$child->isValid()) { return false; } } return true; } /** * Returns the button that was used to submit the form. * * @return Button|null The clicked button or NULL if the form was not * submitted */ public function getClickedButton() { if ($this->clickedButton) { return $this->clickedButton; } if ($this->parent && method_exists($this->parent, 'getClickedButton')) { return $this->parent->getClickedButton(); } return null; } /** * {@inheritdoc} */ public function getErrors() { return $this->errors; } /** * Returns a string representation of all form errors (including children errors). * * This method should only be used to help debug a form. * * @param integer $level The indentation level (used internally) * * @return string A string representation of all errors */ public function getErrorsAsString($level = 0) { $errors = ''; foreach ($this->errors as $error) { $errors .= str_repeat(' ', $level).'ERROR: '.$error->getMessage()."\n"; } foreach ($this->children as $key => $child) { $errors .= str_repeat(' ', $level).$key.":\n"; if ($child instanceof self && $err = $child->getErrorsAsString($level + 4)) { $errors .= $err; } else { $errors .= str_repeat(' ', $level + 4)."No errors\n"; } } return $errors; } /** * {@inheritdoc} */ public function all() { return iterator_to_array($this->children); } /** * {@inheritdoc} */ public function add($child, $type = null, array $options = array()) { if ($this->submitted) { throw new AlreadySubmittedException('You cannot add children to a submitted form'); } if (!$this->config->getCompound()) { throw new LogicException('You cannot add children to a simple form. Maybe you should set the option "compound" to true?'); } // Obtain the view data $viewData = null; // If setData() is currently being called, there is no need to call // mapDataToForms() here, as mapDataToForms() is called at the end // of setData() anyway. Not doing this check leads to an endless // recursion when initializing the form lazily and an event listener // (such as ResizeFormListener) adds fields depending on the data: // // * setData() is called, the form is not initialized yet // * add() is called by the listener (setData() is not complete, so // the form is still not initialized) // * getViewData() is called // * setData() is called since the form is not initialized yet // * ... endless recursion ... // // Also skip data mapping if setData() has not been called yet. // setData() will be called upon form initialization and data mapping // will take place by then. if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) { $viewData = $this->getViewData(); } if (!$child instanceof FormInterface) { if (!is_string($child) && !is_int($child)) { throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormInterface'); } if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) { throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface'); } // Never initialize child forms automatically $options['auto_initialize'] = false; if (null === $type) { $child = $this->config->getFormFactory()->createForProperty($this->config->getDataClass(), $child, null, $options); } else { $child = $this->config->getFormFactory()->createNamed($child, $type, null, $options); } } elseif ($child->getConfig()->getAutoInitialize()) { throw new RuntimeException(sprintf( 'Automatic initialization is only supported on root forms. You '. 'should set the "auto_initialize" option to false on the field "%s".', $child->getName() )); } $this->children[$child->getName()] = $child; $child->setParent($this); if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) { $iterator = new InheritDataAwareIterator(new \ArrayIterator(array($child))); $iterator = new \RecursiveIteratorIterator($iterator); $this->config->getDataMapper()->mapDataToForms($viewData, $iterator); } return $this; } /** * {@inheritdoc} */ public function remove($name) { if ($this->submitted) { throw new AlreadySubmittedException('You cannot remove children from a submitted form'); } if (isset($this->children[$name])) { $this->children[$name]->setParent(null); unset($this->children[$name]); } return $this; } /** * {@inheritdoc} */ public function has($name) { return isset($this->children[$name]); } /** * {@inheritdoc} */ public function get($name) { if (isset($this->children[$name])) { return $this->children[$name]; } throw new OutOfBoundsException(sprintf('Child "%s" does not exist.', $name)); } /** * Returns whether a child with the given name exists (implements the \ArrayAccess interface). * * @param string $name The name of the child * * @return Boolean */ public function offsetExists($name) { return $this->has($name); } /** * Returns the child with the given name (implements the \ArrayAccess interface). * * @param string $name The name of the child * * @return FormInterface The child form * * @throws \OutOfBoundsException If the named child does not exist. */ public function offsetGet($name) { return $this->get($name); } /** * Adds a child to the form (implements the \ArrayAccess interface). * * @param string $name Ignored. The name of the child is used. * @param FormInterface $child The child to be added. * * @throws AlreadySubmittedException If the form has already been submitted. * @throws LogicException When trying to add a child to a non-compound form. * * @see self::add() */ public function offsetSet($name, $child) { $this->add($child); } /** * Removes the child with the given name from the form (implements the \ArrayAccess interface). * * @param string $name The name of the child to remove * * @throws AlreadySubmittedException If the form has already been submitted. */ public function offsetUnset($name) { $this->remove($name); } /** * Returns the iterator for this group. * * @return \Traversable */ public function getIterator() { return $this->children; } /** * Returns the number of form children (implements the \Countable interface). * * @return integer The number of embedded form children */ public function count() { return count($this->children); } /** * {@inheritdoc} */ public function createView(FormView $parent = null) { if (null === $parent && $this->parent) { $parent = $this->parent->createView(); } $type = $this->config->getType(); $options = $this->config->getOptions(); // The methods createView(), buildView() and finishView() are called // explicitly here in order to be able to override either of them // in a custom resolved form type. $view = $type->createView($this, $parent); $type->buildView($view, $this, $options); foreach ($this->children as $name => $child) { $view->children[$name] = $child->createView($view); } $type->finishView($view, $this, $options); return $view; } /** * Normalizes the value if a normalization transformer is set. * * @param mixed $value The value to transform * * @return mixed */ private function modelToNorm($value) { foreach ($this->config->getModelTransformers() as $transformer) { $value = $transformer->transform($value); } return $value; } /** * Reverse transforms a value if a normalization transformer is set. * * @param string $value The value to reverse transform * * @return mixed */ private function normToModel($value) { $transformers = $this->config->getModelTransformers(); for ($i = count($transformers) - 1; $i >= 0; --$i) { $value = $transformers[$i]->reverseTransform($value); } return $value; } /** * Transforms the value if a value transformer is set. * * @param mixed $value The value to transform * * @return mixed */ private function normToView($value) { // Scalar values should be converted to strings to // facilitate differentiation between empty ("") and zero (0). // Only do this for simple forms, as the resulting value in // compound forms is passed to the data mapper and thus should // not be converted to a string before. if (!$this->config->getViewTransformers() && !$this->config->getCompound()) { return null === $value || is_scalar($value) ? (string) $value : $value; } foreach ($this->config->getViewTransformers() as $transformer) { $value = $transformer->transform($value); } return $value; } /** * Reverse transforms a value if a value transformer is set. * * @param string $value The value to reverse transform * * @return mixed */ private function viewToNorm($value) { $transformers = $this->config->getViewTransformers(); if (!$transformers) { return '' === $value ? null : $value; } for ($i = count($transformers) - 1; $i >= 0; --$i) { $value = $transformers[$i]->reverseTransform($value); } return $value; } } PK]ObXqqForm/SubmitButton.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A button that submits the form. * * @author Bernhard Schussek */ class SubmitButton extends Button implements ClickableInterface { /** * @var Boolean */ private $clicked = false; /** * {@inheritdoc} */ public function isClicked() { return $this->clicked; } /** * Submits data to the button. * * @param null|string $submittedData The data. * @param Boolean $clearMissing Not used. * * @return SubmitButton The button instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ public function submit($submittedData, $clearMissing = true) { parent::submit($submittedData, $clearMissing); $this->clicked = null !== $submittedData; return $this; } } PK]\g Form/RequestHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Submits forms if they were submitted. * * @author Bernhard Schussek */ interface RequestHandlerInterface { /** * Submits a form if it was submitted. * * @param FormInterface $form The form to submit. * @param mixed $request The current request. */ public function handleRequest(FormInterface $form, $request = null); } PK]N̷)Form/ResolvedFormTypeFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Creates ResolvedFormTypeInterface instances. * * This interface allows you to use your custom ResolvedFormTypeInterface * implementation, within which you can customize the concrete FormBuilderInterface * implementations or FormView subclasses that are used by the framework. * * @author Bernhard Schussek */ interface ResolvedFormTypeFactoryInterface { /** * Resolves a form type. * * @param FormTypeInterface $type * @param FormTypeExtensionInterface[] $typeExtensions * @param ResolvedFormTypeInterface|null $parent * * @return ResolvedFormTypeInterface * * @throws Exception\UnexpectedTypeException if the types parent {@link FormTypeInterface::getParent()} is not a string * @throws Exception\InvalidArgumentException if the types parent can not be retrieved from any extension */ public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null); } PK]188Form/AbstractType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ abstract class AbstractType implements FormTypeInterface { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { } /** * {@inheritdoc} */ public function getParent() { return 'form'; } } PK])..Form/FormRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * Renders a form into HTML using a rendering engine. * * @author Bernhard Schussek */ class FormRenderer implements FormRendererInterface { const CACHE_KEY_VAR = 'unique_block_prefix'; /** * @var FormRendererEngineInterface */ private $engine; /** * @var CsrfTokenManagerInterface */ private $csrfTokenManager; /** * @var array */ private $blockNameHierarchyMap = array(); /** * @var array */ private $hierarchyLevelMap = array(); /** * @var array */ private $variableStack = array(); /** * Constructor. * * @param FormRendererEngineInterface $engine * @param CsrfTokenManagerInterface|null $csrfTokenManager * * @throws UnexpectedTypeException */ public function __construct(FormRendererEngineInterface $engine, $csrfTokenManager = null) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface or null'); } $this->engine = $engine; $this->csrfTokenManager = $csrfTokenManager; } /** * {@inheritdoc} */ public function getEngine() { return $this->engine; } /** * {@inheritdoc} */ public function setTheme(FormView $view, $themes) { $this->engine->setTheme($view, $themes); } /** * {@inheritdoc} */ public function renderCsrfToken($tokenId) { if (null === $this->csrfTokenManager) { throw new BadMethodCallException('CSRF tokens can only be generated if a CsrfTokenManagerInterface is injected in FormRenderer::__construct().'); } return $this->csrfTokenManager->getToken($tokenId)->getValue(); } /** * {@inheritdoc} */ public function renderBlock(FormView $view, $blockName, array $variables = array()) { $resource = $this->engine->getResourceForBlockName($view, $blockName); if (!$resource) { throw new LogicException(sprintf('No block "%s" found while rendering the form.', $blockName)); } $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; // The variables are cached globally for a view (instead of for the // current suffix) if (!isset($this->variableStack[$viewCacheKey])) { $this->variableStack[$viewCacheKey] = array(); // The default variable scope contains all view variables, merged with // the variables passed explicitly to the helper $scopeVariables = $view->vars; $varInit = true; } else { // Reuse the current scope and merge it with the explicitly passed variables $scopeVariables = end($this->variableStack[$viewCacheKey]); $varInit = false; } // Merge the passed with the existing attributes if (isset($variables['attr']) && isset($scopeVariables['attr'])) { $variables['attr'] = array_replace($scopeVariables['attr'], $variables['attr']); } // Merge the passed with the exist *label* attributes if (isset($variables['label_attr']) && isset($scopeVariables['label_attr'])) { $variables['label_attr'] = array_replace($scopeVariables['label_attr'], $variables['label_attr']); } // Do not use array_replace_recursive(), otherwise array variables // cannot be overwritten $variables = array_replace($scopeVariables, $variables); $this->variableStack[$viewCacheKey][] = $variables; // Do the rendering $html = $this->engine->renderBlock($view, $resource, $blockName, $variables); // Clear the stack array_pop($this->variableStack[$viewCacheKey]); if ($varInit) { unset($this->variableStack[$viewCacheKey]); } return $html; } /** * {@inheritdoc} */ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $variables = array()) { $renderOnlyOnce = 'row' === $blockNameSuffix || 'widget' === $blockNameSuffix; if ($renderOnlyOnce && $view->isRendered()) { return ''; } // The cache key for storing the variables and types $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; $viewAndSuffixCacheKey = $viewCacheKey.$blockNameSuffix; // In templates, we have to deal with two kinds of block hierarchies: // // +---------+ +---------+ // | Theme B | -------> | Theme A | // +---------+ +---------+ // // form_widget -------> form_widget // ^ // | // choice_widget -----> choice_widget // // The first kind of hierarchy is the theme hierarchy. This allows to // override the block "choice_widget" from Theme A in the extending // Theme B. This kind of inheritance needs to be supported by the // template engine and, for example, offers "parent()" or similar // functions to fall back from the custom to the parent implementation. // // The second kind of hierarchy is the form type hierarchy. This allows // to implement a custom "choice_widget" block (no matter in which theme), // or to fallback to the block of the parent type, which would be // "form_widget" in this example (again, no matter in which theme). // If the designer wants to explicitly fallback to "form_widget" in his // custom "choice_widget", for example because he only wants to wrap // a
around the original implementation, he can simply call the // widget() function again to render the block for the parent type. // // The second kind is implemented in the following blocks. if (!isset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey])) { // INITIAL CALL // Calculate the hierarchy of template blocks and start on // the bottom level of the hierarchy (= "__
" block) $blockNameHierarchy = array(); foreach ($view->vars['block_prefixes'] as $blockNamePrefix) { $blockNameHierarchy[] = $blockNamePrefix.'_'.$blockNameSuffix; } $hierarchyLevel = count($blockNameHierarchy) - 1; $hierarchyInit = true; } else { // RECURSIVE CALL // If a block recursively calls searchAndRenderBlock() again, resume rendering // using the parent type in the hierarchy. $blockNameHierarchy = $this->blockNameHierarchyMap[$viewAndSuffixCacheKey]; $hierarchyLevel = $this->hierarchyLevelMap[$viewAndSuffixCacheKey] - 1; $hierarchyInit = false; } // The variables are cached globally for a view (instead of for the // current suffix) if (!isset($this->variableStack[$viewCacheKey])) { $this->variableStack[$viewCacheKey] = array(); // The default variable scope contains all view variables, merged with // the variables passed explicitly to the helper $scopeVariables = $view->vars; $varInit = true; } else { // Reuse the current scope and merge it with the explicitly passed variables $scopeVariables = end($this->variableStack[$viewCacheKey]); $varInit = false; } // Load the resource where this block can be found $resource = $this->engine->getResourceForBlockNameHierarchy($view, $blockNameHierarchy, $hierarchyLevel); // Update the current hierarchy level to the one at which the resource was // found. For example, if looking for "choice_widget", but only a resource // is found for its parent "form_widget", then the level is updated here // to the parent level. $hierarchyLevel = $this->engine->getResourceHierarchyLevel($view, $blockNameHierarchy, $hierarchyLevel); // The actually existing block name in $resource $blockName = $blockNameHierarchy[$hierarchyLevel]; // Escape if no resource exists for this block if (!$resource) { throw new LogicException(sprintf( 'Unable to render the form as none of the following blocks exist: "%s".', implode('", "', array_reverse($blockNameHierarchy)) )); } // Merge the passed with the existing attributes if (isset($variables['attr']) && isset($scopeVariables['attr'])) { $variables['attr'] = array_replace($scopeVariables['attr'], $variables['attr']); } // Merge the passed with the exist *label* attributes if (isset($variables['label_attr']) && isset($scopeVariables['label_attr'])) { $variables['label_attr'] = array_replace($scopeVariables['label_attr'], $variables['label_attr']); } // Do not use array_replace_recursive(), otherwise array variables // cannot be overwritten $variables = array_replace($scopeVariables, $variables); // In order to make recursive calls possible, we need to store the block hierarchy, // the current level of the hierarchy and the variables so that this method can // resume rendering one level higher of the hierarchy when it is called recursively. // // We need to store these values in maps (associative arrays) because within a // call to widget() another call to widget() can be made, but for a different view // object. These nested calls should not override each other. $this->blockNameHierarchyMap[$viewAndSuffixCacheKey] = $blockNameHierarchy; $this->hierarchyLevelMap[$viewAndSuffixCacheKey] = $hierarchyLevel; // We also need to store the variables for the view so that we can render other // blocks for the same view using the same variables as in the outer block. $this->variableStack[$viewCacheKey][] = $variables; // Do the rendering $html = $this->engine->renderBlock($view, $resource, $blockName, $variables); // Clear the stack array_pop($this->variableStack[$viewCacheKey]); // Clear the caches if they were filled for the first time within // this function call if ($hierarchyInit) { unset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey]); unset($this->hierarchyLevelMap[$viewAndSuffixCacheKey]); } if ($varInit) { unset($this->variableStack[$viewCacheKey]); } if ($renderOnlyOnce) { $view->setRendered(); } return $html; } /** * {@inheritdoc} */ public function humanize($text) { return ucfirst(trim(strtolower(preg_replace(array('/([A-Z])/', '/[_\s]+/'), array('_$1', ' '), $text)))); } } PK]CForm/AbstractTypeExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ abstract class AbstractTypeExtension implements FormTypeExtensionInterface { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { } } PK]"Form/FormEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\EventDispatcher\Event; /** * @author Bernhard Schussek */ class FormEvent extends Event { private $form; protected $data; /** * Constructs an event. * * @param FormInterface $form The associated form * @param mixed $data The data */ public function __construct(FormInterface $form, $data) { $this->form = $form; $this->data = $data; } /** * Returns the form at the source of the event. * * @return FormInterface */ public function getForm() { return $this->form; } /** * Returns the data associated with this event. * * @return mixed */ public function getData() { return $this->data; } /** * Allows updating with some filtered data. * * @param mixed $data */ public function setData($data) { $this->data = $data; } } PK]-9NNForm/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector; use Symfony\Component\CssSelector\Parser\Shortcut\ClassParser; use Symfony\Component\CssSelector\Parser\Shortcut\ElementParser; use Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser; use Symfony\Component\CssSelector\Parser\Shortcut\HashParser; use Symfony\Component\CssSelector\XPath\Extension\HtmlExtension; use Symfony\Component\CssSelector\XPath\Translator; /** * CssSelector is the main entry point of the component and can convert CSS * selectors to XPath expressions. * * $xpath = CssSelector::toXpath('h1.foo'); * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Fabien Potencier * * @api */ class CssSelector { private static $html = true; /** * Translates a CSS expression to its XPath equivalent. * Optionally, a prefix can be added to the resulting XPath * expression with the $prefix parameter. * * @param mixed $cssExpr The CSS expression. * @param string $prefix An optional prefix for the XPath expression. * * @return string * * @api */ public static function toXPath($cssExpr, $prefix = 'descendant-or-self::') { $translator = new Translator(); if (self::$html) { $translator->registerExtension(new HtmlExtension($translator)); } $translator ->registerParserShortcut(new EmptyStringParser()) ->registerParserShortcut(new ElementParser()) ->registerParserShortcut(new ClassParser()) ->registerParserShortcut(new HashParser()) ; return $translator->cssToXPath($cssExpr, $prefix); } /** * Enables the HTML extension. */ public static function enableHtmlExtension() { self::$html = true; } /** * Disables the HTML extension. */ public static function disableHtmlExtension() { self::$html = false; } } PK]zZ< CssSelector/Parser/Token.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; /** * CSS selector token. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class Token { const TYPE_FILE_END = 'eof'; const TYPE_DELIMITER = 'delimiter'; const TYPE_WHITESPACE = 'whitespace'; const TYPE_IDENTIFIER = 'identifier'; const TYPE_HASH = 'hash'; const TYPE_NUMBER = 'number'; const TYPE_STRING = 'string'; /** * @var int */ private $type; /** * @var string */ private $value; /** * @var int */ private $position; /** * @param int $type * @param string $value * @param int $position */ public function __construct($type, $value, $position) { $this->type = $type; $this->value = $value; $this->position = $position; } /** * @return int */ public function getType() { return $this->type; } /** * @return string */ public function getValue() { return $this->value; } /** * @return int */ public function getPosition() { return $this->position; } /** * @return boolean */ public function isFileEnd() { return self::TYPE_FILE_END === $this->type; } /** * @param array $values * * @return boolean */ public function isDelimiter(array $values = array()) { if (self::TYPE_DELIMITER !== $this->type) { return false; } if (empty($values)) { return true; } return in_array($this->value, $values); } /** * @return boolean */ public function isWhitespace() { return self::TYPE_WHITESPACE === $this->type; } /** * @return boolean */ public function isIdentifier() { return self::TYPE_IDENTIFIER === $this->type; } /** * @return boolean */ public function isHash() { return self::TYPE_HASH === $this->type; } /** * @return boolean */ public function isNumber() { return self::TYPE_NUMBER === $this->type; } /** * @return boolean */ public function isString() { return self::TYPE_STRING === $this->type; } /** * @return string */ public function __toString() { if ($this->value) { return sprintf('<%s "%s" at %s>', $this->type, $this->value, $this->position); } return sprintf('<%s at %s>', $this->type, $this->position); } } PK]QQ"CssSelector/Parser/TokenStream.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; use Symfony\Component\CssSelector\Exception\InternalErrorException; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; /** * CSS selector token stream. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class TokenStream { /** * @var Token[] */ private $tokens = array(); /** * @var boolean */ private $frozen = false; /** * @var Token[] */ private $used = array(); /** * @var int */ private $cursor = 0; /** * @var Token|null */ private $peeked = null; /** * @var boolean */ private $peeking = false; /** * Pushes a token. * * @param Token $token * * @return TokenStream */ public function push(Token $token) { $this->tokens[] = $token; return $this; } /** * Freezes stream. * * @return TokenStream */ public function freeze() { $this->frozen = true; return $this; } /** * Returns next token. * * @throws InternalErrorException If there is no more token * * @return Token */ public function getNext() { if ($this->peeking) { $this->peeking = false; $this->used[] = $this->peeked; return $this->peeked; } if (!isset($this->tokens[$this->cursor])) { throw new InternalErrorException('Unexpected token stream end.'); } return $this->tokens[$this->cursor ++]; } /** * Returns peeked token. * * @return Token */ public function getPeek() { if (!$this->peeking) { $this->peeked = $this->getNext(); $this->peeking = true; } return $this->peeked; } /** * Returns used tokens. * * @return Token[] */ public function getUsed() { return $this->used; } /** * Returns nex identifier token. * * @throws SyntaxErrorException If next token is not an identifier * * @return string The identifier token value */ public function getNextIdentifier() { $next = $this->getNext(); if (!$next->isIdentifier()) { throw SyntaxErrorException::unexpectedToken('identifier', $next); } return $next->getValue(); } /** * Returns nex identifier or star delimiter token. * * @throws SyntaxErrorException If next token is not an identifier or a star delimiter * * @return null|string The identifier token value or null if star found */ public function getNextIdentifierOrStar() { $next = $this->getNext(); if ($next->isIdentifier()) { return $next->getValue(); } if ($next->isDelimiter(array('*'))) { return null; } throw SyntaxErrorException::unexpectedToken('identifier or "*"', $next); } /** * Skips next whitespace if any. */ public function skipWhitespace() { $peek = $this->getPeek(); if ($peek->isWhitespace()) { $this->getNext(); } } } PK]6ND1D1CssSelector/Parser/Parser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; use Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\Parser\Tokenizer\Tokenizer; /** * CSS selector parser. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class Parser implements ParserInterface { /** * @var Tokenizer */ private $tokenizer; /** * Constructor. * * @param null|Tokenizer $tokenizer */ public function __construct(Tokenizer $tokenizer = null) { $this->tokenizer = $tokenizer ?: new Tokenizer(); } /** * {@inheritdoc} */ public function parse($source) { $reader = new Reader($source); $stream = $this->tokenizer->tokenize($reader); return $this->parseSelectorList($stream); } /** * Parses the arguments for ":nth-child()" and friends. * * @param Token[] $tokens * * @throws SyntaxErrorException * * @return array */ public static function parseSeries(array $tokens) { foreach ($tokens as $token) { if ($token->isString()) { throw SyntaxErrorException::stringAsFunctionArgument(); } } $joined = trim(implode('', array_map(function (Token $token) { return $token->getValue(); }, $tokens))); $int = function ($string) { if (!is_numeric($string)) { throw SyntaxErrorException::stringAsFunctionArgument(); } return (int) $string; }; switch (true) { case 'odd' === $joined: return array(2, 1); case 'even' === $joined: return array(2, 0); case 'n' === $joined: return array(1, 0); case false === strpos($joined, 'n'): return array(0, $int($joined)); } $split = explode('n', $joined); $first = isset($split[0]) ? $split[0] : null; return array( $first ? ('-' === $first || '+' === $first ? $int($first.'1') : $int($first)) : 1, isset($split[1]) && $split[1] ? $int($split[1]) : 0 ); } /** * Parses selector nodes. * * @param TokenStream $stream * * @return array */ private function parseSelectorList(TokenStream $stream) { $stream->skipWhitespace(); $selectors = array(); while (true) { $selectors[] = $this->parserSelectorNode($stream); if ($stream->getPeek()->isDelimiter(array(','))) { $stream->getNext(); $stream->skipWhitespace(); } else { break; } } return $selectors; } /** * Parses next selector or combined node. * * @param TokenStream $stream * * @throws SyntaxErrorException * * @return Node\SelectorNode */ private function parserSelectorNode(TokenStream $stream) { list($result, $pseudoElement) = $this->parseSimpleSelector($stream); while (true) { $stream->skipWhitespace(); $peek = $stream->getPeek(); if ($peek->isFileEnd() || $peek->isDelimiter(array(','))) { break; } if (null !== $pseudoElement) { throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector'); } if ($peek->isDelimiter(array('+', '>', '~'))) { $combinator = $stream->getNext()->getValue(); $stream->skipWhitespace(); } else { $combinator = ' '; } list($nextSelector, $pseudoElement) = $this->parseSimpleSelector($stream); $result = new Node\CombinedSelectorNode($result, $combinator, $nextSelector); } return new Node\SelectorNode($result, $pseudoElement); } /** * Parses next simple node (hash, class, pseudo, negation). * * @param TokenStream $stream * @param boolean $insideNegation * * @throws SyntaxErrorException * * @return array */ private function parseSimpleSelector(TokenStream $stream, $insideNegation = false) { $stream->skipWhitespace(); $selectorStart = count($stream->getUsed()); $result = $this->parseElementNode($stream); $pseudoElement = null; while (true) { $peek = $stream->getPeek(); if ($peek->isWhitespace() || $peek->isFileEnd() || $peek->isDelimiter(array(',', '+', '>', '~')) || ($insideNegation && $peek->isDelimiter(array(')'))) ) { break; } if (null !== $pseudoElement) { throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector'); } if ($peek->isHash()) { $result = new Node\HashNode($result, $stream->getNext()->getValue()); } elseif ($peek->isDelimiter(array('.'))) { $stream->getNext(); $result = new Node\ClassNode($result, $stream->getNextIdentifier()); } elseif ($peek->isDelimiter(array('['))) { $stream->getNext(); $result = $this->parseAttributeNode($result, $stream); } elseif ($peek->isDelimiter(array(':'))) { $stream->getNext(); if ($stream->getPeek()->isDelimiter(array(':'))) { $stream->getNext(); $pseudoElement = $stream->getNextIdentifier(); continue; } $identifier = $stream->getNextIdentifier(); if (in_array(strtolower($identifier), array('first-line', 'first-letter', 'before', 'after'))) { // Special case: CSS 2.1 pseudo-elements can have a single ':'. // Any new pseudo-element must have two. $pseudoElement = $identifier; continue; } if (!$stream->getPeek()->isDelimiter(array('('))) { $result = new Node\PseudoNode($result, $identifier); continue; } $stream->getNext(); $stream->skipWhitespace(); if ('not' === strtolower($identifier)) { if ($insideNegation) { throw SyntaxErrorException::nestedNot(); } list($argument, $argumentPseudoElement) = $this->parseSimpleSelector($stream, true); $next = $stream->getNext(); if (null !== $argumentPseudoElement) { throw SyntaxErrorException::pseudoElementFound($argumentPseudoElement, 'inside ::not()'); } if (!$next->isDelimiter(array(')'))) { throw SyntaxErrorException::unexpectedToken('")"', $next); } $result = new Node\NegationNode($result, $argument); } else { $arguments = array(); $next = null; while (true) { $stream->skipWhitespace(); $next = $stream->getNext(); if ($next->isIdentifier() || $next->isString() || $next->isNumber() || $next->isDelimiter(array('+', '-')) ) { $arguments[] = $next; } elseif ($next->isDelimiter(array(')'))) { break; } else { throw SyntaxErrorException::unexpectedToken('an argument', $next); } } if (empty($arguments)) { throw SyntaxErrorException::unexpectedToken('at least one argument', $next); } $result = new Node\FunctionNode($result, $identifier, $arguments); } } else { throw SyntaxErrorException::unexpectedToken('selector', $peek); } } if (count($stream->getUsed()) === $selectorStart) { throw SyntaxErrorException::unexpectedToken('selector', $stream->getPeek()); } return array($result, $pseudoElement); } /** * Parses next element node. * * @param TokenStream $stream * * @return Node\ElementNode */ private function parseElementNode(TokenStream $stream) { $peek = $stream->getPeek(); if ($peek->isIdentifier() || $peek->isDelimiter(array('*'))) { if ($peek->isIdentifier()) { $namespace = $stream->getNext()->getValue(); } else { $stream->getNext(); $namespace = null; } if ($stream->getPeek()->isDelimiter(array('|'))) { $stream->getNext(); $element = $stream->getNextIdentifierOrStar(); } else { $element = $namespace; $namespace = null; } } else { $element = $namespace = null; } return new Node\ElementNode($namespace, $element); } /** * Parses next attribute node. * * @param Node\NodeInterface $selector * @param TokenStream $stream * * @throws SyntaxErrorException * * @return Node\AttributeNode */ private function parseAttributeNode(Node\NodeInterface $selector, TokenStream $stream) { $stream->skipWhitespace(); $attribute = $stream->getNextIdentifierOrStar(); if (null === $attribute && !$stream->getPeek()->isDelimiter(array('|'))) { throw SyntaxErrorException::unexpectedToken('"|"', $stream->getPeek()); } if ($stream->getPeek()->isDelimiter(array('|'))) { $stream->getNext(); if ($stream->getPeek()->isDelimiter(array('='))) { $namespace = null; $stream->getNext(); $operator = '|='; } else { $namespace = $attribute; $attribute = $stream->getNextIdentifier(); $operator = null; } } else { $namespace = $operator = null; } if (null === $operator) { $stream->skipWhitespace(); $next = $stream->getNext(); if ($next->isDelimiter(array(']'))) { return new Node\AttributeNode($selector, $namespace, $attribute, 'exists', null); } elseif ($next->isDelimiter(array('='))) { $operator = '='; } elseif ($next->isDelimiter(array('^', '$', '*', '~', '|', '!')) && $stream->getPeek()->isDelimiter(array('=')) ) { $operator = $next->getValue().'='; $stream->getNext(); } else { throw SyntaxErrorException::unexpectedToken('operator', $next); } } $stream->skipWhitespace(); $value = $stream->getNext(); if ($value->isNumber()) { // if the value is a number, it's casted into a string $value = new Token(Token::TYPE_STRING, (string) $value->getValue(), $value->getPosition()); } if (!($value->isIdentifier() || $value->isString())) { throw SyntaxErrorException::unexpectedToken('string or identifier', $value); } $stream->skipWhitespace(); $next = $stream->getNext(); if (!$next->isDelimiter(array(']'))) { throw SyntaxErrorException::unexpectedToken('"]"', $next); } return new Node\AttributeNode($selector, $namespace, $attribute, $operator, $value->getValue()); } } PK];  CssSelector/Parser/Reader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; /** * CSS selector reader. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class Reader { /** * @var string */ private $source; /** * @var int */ private $length; /** * @var int */ private $position = 0; /** * @param string $source */ public function __construct($source) { $this->source = $source; $this->length = strlen($source); } /** * @return bool */ public function isEOF() { return $this->position >= $this->length; } /** * @return int */ public function getPosition() { return $this->position; } /** * @return int */ public function getRemainingLength() { return $this->length - $this->position; } /** * @param int $length * @param int $offset * * @return string */ public function getSubstring($length, $offset = 0) { return substr($this->source, $this->position + $offset, $length); } /** * @param string $string * * @return int */ public function getOffset($string) { $position = strpos($this->source, $string, $this->position); return false === $position ? false : $position - $this->position; } /** * @param string $pattern * * @return bool */ public function findPattern($pattern) { $source = substr($this->source, $this->position); if (preg_match($pattern, $source, $matches)) { return $matches; } return false; } /** * @param int $length */ public function moveForward($length) { $this->position += $length; } /** */ public function moveToEnd() { $this->position = $this->length; } } PK]SkFF*CssSelector/Parser/Tokenizer/Tokenizer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Tokenizer; use Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector tokenizer. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class Tokenizer { /** * @var Handler\HandlerInterface[] */ private $handlers; /** * Constructor. */ public function __construct() { $patterns = new TokenizerPatterns(); $escaping = new TokenizerEscaping($patterns); $this->handlers = array( new Handler\WhitespaceHandler(), new Handler\IdentifierHandler($patterns, $escaping), new Handler\HashHandler($patterns, $escaping), new Handler\StringHandler($patterns, $escaping), new Handler\NumberHandler($patterns), new Handler\CommentHandler(), ); } /** * Tokenize selector source code. * * @param Reader $reader * * @return TokenStream */ public function tokenize(Reader $reader) { $stream = new TokenStream(); while (!$reader->isEOF()) { foreach ($this->handlers as $handler) { if ($handler->handle($reader, $stream)) { continue 2; } } $stream->push(new Token(Token::TYPE_DELIMITER, $reader->getSubstring(1), $reader->getPosition())); $reader->moveForward(1); } return $stream ->push(new Token(Token::TYPE_FILE_END, null, $reader->getPosition())) ->freeze(); } } PK]>< 2CssSelector/Parser/Tokenizer/TokenizerPatterns.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Tokenizer; /** * CSS selector tokenizer patterns builder. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class TokenizerPatterns { /** * @var string */ private $unicodeEscapePattern; /** * @var string */ private $simpleEscapePattern; /** * @var string */ private $newLineEscapePattern; /** * @var string */ private $escapePattern; /** * @var string */ private $stringEscapePattern; /** * @var string */ private $nonAsciiPattern; /** * @var string */ private $nmCharPattern; /** * @var string */ private $nmStartPattern; /** * @var string */ private $identifierPattern; /** * @var string */ private $hashPattern; /** * @var string */ private $numberPattern; /** * @var string */ private $quotedStringPattern; /** * Constructor. */ public function __construct() { $this->unicodeEscapePattern = '\\\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?'; $this->simpleEscapePattern = '\\\\(.)'; $this->newLineEscapePattern = '\\\\(?:\n|\r\n|\r|\f)'; $this->escapePattern = $this->unicodeEscapePattern.'|\\\\[^\n\r\f0-9a-f]'; $this->stringEscapePattern = $this->newLineEscapePattern.'|'.$this->escapePattern; $this->nonAsciiPattern = '[^\x00-\x7F]'; $this->nmCharPattern = '[_a-z0-9-]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; $this->nmStartPattern = '[_a-z]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; $this->identifierPattern = '(?:'.$this->nmStartPattern.')(?:'.$this->nmCharPattern.')*'; $this->hashPattern = '#((?:'.$this->nmCharPattern.')+)'; $this->numberPattern = '[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)'; $this->quotedStringPattern = '([^\n\r\f%s]|'.$this->stringEscapePattern.')*'; } /** * @return string */ public function getNewLineEscapePattern() { return '~^'.$this->newLineEscapePattern.'~'; } /** * @return string */ public function getSimpleEscapePattern() { return '~^'.$this->simpleEscapePattern.'~'; } /** * @return string */ public function getUnicodeEscapePattern() { return '~^'.$this->unicodeEscapePattern.'~i'; } /** * @return string */ public function getIdentifierPattern() { return '~^'.$this->identifierPattern.'~i'; } /** * @return string */ public function getHashPattern() { return '~^'.$this->hashPattern.'~i'; } /** * @return string */ public function getNumberPattern() { return '~^'.$this->numberPattern.'~'; } /** * @param string $quote * * @return string */ public function getQuotedStringPattern($quote) { return '~^'.sprintf($this->quotedStringPattern, $quote).'~i'; } } PK] W552CssSelector/Parser/Tokenizer/TokenizerEscaping.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Tokenizer; /** * CSS selector tokenizer escaping applier. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class TokenizerEscaping { /** * @var TokenizerPatterns */ private $patterns; /** * @param TokenizerPatterns $patterns */ public function __construct(TokenizerPatterns $patterns) { $this->patterns = $patterns; } /** * @param string $value * * @return string */ public function escapeUnicode($value) { $value = $this->replaceUnicodeSequences($value); return preg_replace($this->patterns->getSimpleEscapePattern(), '$1', $value); } /** * @param string $value * * @return string */ public function escapeUnicodeAndNewLine($value) { $value = preg_replace($this->patterns->getNewLineEscapePattern(), '', $value); return $this->escapeUnicode($value); } /** * @param string $value * * @return string */ private function replaceUnicodeSequences($value) { return preg_replace_callback($this->patterns->getUnicodeEscapePattern(), function (array $match) { $code = $match[1]; if (bin2hex($code) > 0xFFFD) { $code = '\\FFFD'; } return mb_convert_encoding(pack('H*', $code), 'UTF-8', 'UCS-2BE'); }, $value); } } PK]6\5 5 ,CssSelector/Parser/Handler/StringHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Exception\InternalErrorException; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; /** * CSS selector comment handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class StringHandler implements HandlerInterface { /** * @var TokenizerPatterns */ private $patterns; /** * @var TokenizerEscaping */ private $escaping; /** * @param TokenizerPatterns $patterns * @param TokenizerEscaping $escaping */ public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) { $this->patterns = $patterns; $this->escaping = $escaping; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { $quote = $reader->getSubstring(1); if (!in_array($quote, array("'", '"'))) { return false; } $reader->moveForward(1); $match = $reader->findPattern($this->patterns->getQuotedStringPattern($quote)); if (!$match) { throw new InternalErrorException(sprintf('Should have found at least an empty match at %s.', $reader->getPosition())); } // check unclosed strings if (strlen($match[0]) === $reader->getRemainingLength()) { throw SyntaxErrorException::unclosedString($reader->getPosition() - 1); } // check quotes pairs validity if ($quote !== $reader->getSubstring(1, strlen($match[0]))) { throw SyntaxErrorException::unclosedString($reader->getPosition() - 1); } $string = $this->escaping->escapeUnicodeAndNewLine($match[0]); $stream->push(new Token(Token::TYPE_STRING, $string, $reader->getPosition())); $reader->moveForward(strlen($match[0]) + 1); return true; } } PK]hff/CssSelector/Parser/Handler/HandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector handler interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface HandlerInterface { /** * @param Reader $reader * @param TokenStream $stream * * @return boolean */ public function handle(Reader $reader, TokenStream $stream); } PK]0CssSelector/Parser/Handler/WhitespaceHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector whitespace handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class WhitespaceHandler implements HandlerInterface { /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { $match = $reader->findPattern('~^[ \t\r\n\f]+~'); if (false === $match) { return false; } $stream->push(new Token(Token::TYPE_WHITESPACE, $match[0], $reader->getPosition())); $reader->moveForward(strlen($match[0])); return true; } } PK]X{*CssSelector/Parser/Handler/HashHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; /** * CSS selector comment handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class HashHandler implements HandlerInterface { /** * @var TokenizerPatterns */ private $patterns; /** * @var TokenizerEscaping */ private $escaping; /** * @param TokenizerPatterns $patterns * @param TokenizerEscaping $escaping */ public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) { $this->patterns = $patterns; $this->escaping = $escaping; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { $match = $reader->findPattern($this->patterns->getHashPattern()); if (!$match) { return false; } $value = $this->escaping->escapeUnicode($match[1]); $stream->push(new Token(Token::TYPE_HASH, $value, $reader->getPosition())); $reader->moveForward(strlen($match[0])); return true; } } PK]8D^^-CssSelector/Parser/Handler/CommentHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector comment handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class CommentHandler implements HandlerInterface { /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { if ('/*' !== $reader->getSubstring(2)) { return false; } $offset = $reader->getOffset('*/'); if (false === $offset) { $reader->moveToEnd(); } else { $reader->moveForward($offset + 2); } return true; } } PK]e'n,CssSelector/Parser/Handler/NumberHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; /** * CSS selector comment handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class NumberHandler implements HandlerInterface { /** * @var TokenizerPatterns */ private $patterns; /** * @param TokenizerPatterns $patterns */ public function __construct(TokenizerPatterns $patterns) { $this->patterns = $patterns; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { $match = $reader->findPattern($this->patterns->getNumberPattern()); if (!$match) { return false; } $stream->push(new Token(Token::TYPE_NUMBER, $match[0], $reader->getPosition())); $reader->moveForward(strlen($match[0])); return true; } } PK]#0CssSelector/Parser/Handler/IdentifierHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; /** * CSS selector comment handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class IdentifierHandler implements HandlerInterface { /** * @var TokenizerPatterns */ private $patterns; /** * @var TokenizerEscaping */ private $escaping; /** * @param TokenizerPatterns $patterns * @param TokenizerEscaping $escaping */ public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) { $this->patterns = $patterns; $this->escaping = $escaping; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { $match = $reader->findPattern($this->patterns->getIdentifierPattern()); if (!$match) { return false; } $value = $this->escaping->escapeUnicode($match[0]); $stream->push(new Token(Token::TYPE_IDENTIFIER, $value, $reader->getPosition())); $reader->moveForward(strlen($match[0])); return true; } } PK]ҵܗ1CssSelector/Parser/Shortcut/EmptyStringParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector class parser shortcut. * * This shortcut ensure compatibility with previous version. * - The parser fails to parse an empty string. * - In the previous version, an empty string matches each tags. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class EmptyStringParser implements ParserInterface { /** * {@inheritdoc} */ public function parse($source) { // Matches an empty string if ($source == '') { return array(new SelectorNode(new ElementNode(null, '*'))); } return array(); } } PK]TR#[PP+CssSelector/Parser/Shortcut/ClassParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ClassNode; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector class parser shortcut. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class ClassParser implements ParserInterface { /** * {@inheritdoc} */ public function parse($source) { // Matches an optional namespace, optional element, and required class // $source = 'test|input.ab6bd_field'; // $matches = array (size=5) // 0 => string 'test:input.ab6bd_field' (length=22) // 1 => string 'test:' (length=5) // 2 => string 'test' (length=4) // 3 => string 'input' (length=5) // 4 => string 'ab6bd_field' (length=11) if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)?\.([\w-]+)$/i', trim($source), $matches)) { return array( new SelectorNode(new ClassNode(new ElementNode($matches[2] ?: null, $matches[3] ?: null), $matches[4])) ); } return array(); } } PK]Z>-CssSelector/Parser/Shortcut/ElementParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector element parser shortcut. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class ElementParser implements ParserInterface { /** * {@inheritdoc} */ public function parse($source) { // Matches an optional namespace, required element or `*` // $source = 'testns|testel'; // $matches = array (size=4) // 0 => string 'testns:testel' (length=13) // 1 => string 'testns:' (length=7) // 2 => string 'testns' (length=6) // 3 => string 'testel' (length=6) if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)$/i', trim($source), $matches)) { return array(new SelectorNode(new ElementNode($matches[2] ?: null, $matches[3]))); } return array(); } } PK]5# HH*CssSelector/Parser/Shortcut/HashParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\HashNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector hash parser shortcut. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class HashParser implements ParserInterface { /** * {@inheritdoc} */ public function parse($source) { // Matches an optional namespace, optional element, and required id // $source = 'test|input#ab6bd_field'; // $matches = array (size=5) // 0 => string 'test:input#ab6bd_field' (length=22) // 1 => string 'test:' (length=5) // 2 => string 'test' (length=4) // 3 => string 'input' (length=5) // 4 => string 'ab6bd_field' (length=11) if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)?#([\w-]+)$/i', trim($source), $matches)) { return array( new SelectorNode(new HashNode(new ElementNode($matches[2] ?: null, $matches[3] ?: null), $matches[4])) ); } return array(); } } PK]AEo11&CssSelector/Parser/ParserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; use Symfony\Component\CssSelector\Node\SelectorNode; /** * CSS selector parser interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface ParserInterface { /** * Parses given selector source into an array of tokens. * * @param string $source * * @return SelectorNode[] */ public function parse($source); } PK]gfGBB,CssSelector/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * Interface for exceptions. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface ExceptionInterface { } PK]/pTС2CssSelector/Exception/ExpressionErrorException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class ExpressionErrorException extends ParseException implements ExceptionInterface { } PK]mc0CssSelector/Exception/InternalErrorException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class InternalErrorException extends ParseException implements ExceptionInterface { } PK]מ.CssSelector/Exception/SyntaxErrorException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; use Symfony\Component\CssSelector\Parser\Token; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class SyntaxErrorException extends ParseException implements ExceptionInterface { /** * @param string $expectedValue * @param Token $foundToken * * @return SyntaxErrorException */ public static function unexpectedToken($expectedValue, Token $foundToken) { return new self(sprintf('Expected %s, but %s found.', $expectedValue, $foundToken)); } /** * @param string $pseudoElement * @param string $unexpectedLocation * * @return SyntaxErrorException */ public static function pseudoElementFound($pseudoElement, $unexpectedLocation) { return new self(sprintf('Unexpected pseudo-element "::%s" found %s.', $pseudoElement, $unexpectedLocation)); } /** * @param int $position * * @return SyntaxErrorException */ public static function unclosedString($position) { return new self(sprintf('Unclosed/invalid string at %s.', $position)); } /** * @return SyntaxErrorException */ public static function nestedNot() { return new self('Got nested ::not().'); } /** * @return SyntaxErrorException */ public static function stringAsFunctionArgument() { return new self('String not allowed as function argument.'); } } PK]'[|ɀ(CssSelector/Exception/ParseException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Fabien Potencier */ class ParseException extends \Exception implements ExceptionInterface { } PK]pM2!CssSelector/Node/AbstractNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Abstract base node class. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ abstract class AbstractNode implements NodeInterface { /** * @var string */ private $nodeName; /** * @return string */ public function getNodeName() { if (null === $this->nodeName) { $this->nodeName = preg_replace('~.*\\\\([^\\\\]+)Node$~', '$1', get_called_class()); } return $this->nodeName; } } PK]#^[CssSelector/Node/HashNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "#" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class HashNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $id; /** * @param NodeInterface $selector * @param string $id */ public function __construct(NodeInterface $selector, $id) { $this->selector = $selector; $this->id = $id; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getId() { return $this->id; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus(new Specificity(1, 0, 0)); } /** * {@inheritdoc} */ public function __toString() { return sprintf('%s[%s#%s]', $this->getNodeName(), $this->selector, $this->id); } } PK]Г^FF CssSelector/Node/ElementNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "|" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class ElementNode extends AbstractNode { /** * @var string|null */ private $namespace; /** * @var string|null */ private $element; /** * @param string|null $namespace * @param string|null $element */ public function __construct($namespace = null, $element = null) { $this->namespace = $namespace; $this->element = $element; } /** * @return null|string */ public function getNamespace() { return $this->namespace; } /** * @return null|string */ public function getElement() { return $this->element; } /** * {@inheritdoc} */ public function getSpecificity() { return new Specificity(0, 0, $this->element ? 1 : 0); } /** * {@inheritdoc} */ public function __toString() { $element = $this->element ?: '*'; return sprintf('%s[%s]', $this->getNodeName(), $this->namespace ? $this->namespace.'|'.$element : $element); } } PK]x CssSelector/Node/Specificity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a node specificity. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @see http://www.w3.org/TR/selectors/#specificity * * @author Jean-François Simon */ class Specificity { const A_FACTOR = 100; const B_FACTOR = 10; const C_FACTOR = 1; /** * @var int */ private $a; /** * @var int */ private $b; /** * @var int */ private $c; /** * Constructor. * * @param int $a * @param int $b * @param int $c */ public function __construct($a, $b, $c) { $this->a = $a; $this->b = $b; $this->c = $c; } /** * @param Specificity $specificity * * @return Specificity */ public function plus(Specificity $specificity) { return new self($this->a + $specificity->a, $this->b + $specificity->b, $this->c + $specificity->c); } /** * Returns global specificity value. * * @return int */ public function getValue() { return $this->a * self::A_FACTOR + $this->b * self::B_FACTOR + $this->c * self::C_FACTOR; } } PK]x!CssSelector/Node/FunctionNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\Parser\Token; /** * Represents a ":()" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class FunctionNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $name; /** * @var Token[] */ private $arguments; /** * @param NodeInterface $selector * @param string $name * @param Token[] $arguments */ public function __construct(NodeInterface $selector, $name, array $arguments = array()) { $this->selector = $selector; $this->name = strtolower($name); $this->arguments = $arguments; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getName() { return $this->name; } /** * @return Token[] */ public function getArguments() { return $this->arguments; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } /** * {@inheritdoc} */ public function __toString() { $arguments = implode(', ', array_map(function (Token $token) { return "'".$token->getValue()."'"; }, $this->arguments)); return sprintf('%s[%s:%s(%s)]', $this->getNodeName(), $this->selector, $this->name, $arguments ? '['.$arguments.']' : ''); } } PK],+?)CssSelector/Node/CombinedSelectorNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a combined node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class CombinedSelectorNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $combinator; /** * @var NodeInterface */ private $subSelector; /** * @param NodeInterface $selector * @param string $combinator * @param NodeInterface $subSelector */ public function __construct(NodeInterface $selector, $combinator, NodeInterface $subSelector) { $this->selector = $selector; $this->combinator = $combinator; $this->subSelector = $subSelector; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getCombinator() { return $this->combinator; } /** * @return NodeInterface */ public function getSubSelector() { return $this->subSelector; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); } /** * {@inheritdoc} */ public function __toString() { $combinator = ' ' === $this->combinator ? '' : $this->combinator; return sprintf('%s[%s %s %s]', $this->getNodeName(), $this->selector, $combinator, $this->subSelector); } } PK]!CssSelector/Node/SelectorNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "(::|:)" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class SelectorNode extends AbstractNode { /** * @var NodeInterface */ private $tree; /** * @var null|string */ private $pseudoElement; /** * @param NodeInterface $tree * @param null|string $pseudoElement */ public function __construct(NodeInterface $tree, $pseudoElement = null) { $this->tree = $tree; $this->pseudoElement = $pseudoElement ? strtolower($pseudoElement) : null; } /** * @return NodeInterface */ public function getTree() { return $this->tree; } /** * @return null|string */ public function getPseudoElement() { return $this->pseudoElement; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->tree->getSpecificity()->plus(new Specificity(0, 0, $this->pseudoElement ? 1 : 0)); } /** * {@inheritdoc} */ public function __toString() { return sprintf('%s[%s%s]', $this->getNodeName(), $this->tree, $this->pseudoElement ? '::'.$this->pseudoElement : ''); } } PK]FK K "CssSelector/Node/AttributeNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "[| ]" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class AttributeNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $namespace; /** * @var string */ private $attribute; /** * @var string */ private $operator; /** * @var string */ private $value; /** * @param NodeInterface $selector * @param string $namespace * @param string $attribute * @param string $operator * @param string $value */ public function __construct(NodeInterface $selector, $namespace, $attribute, $operator, $value) { $this->selector = $selector; $this->namespace = $namespace; $this->attribute = $attribute; $this->operator = $operator; $this->value = $value; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getNamespace() { return $this->namespace; } /** * @return string */ public function getAttribute() { return $this->attribute; } /** * @return string */ public function getOperator() { return $this->operator; } /** * @return string */ public function getValue() { return $this->value; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } /** * {@inheritdoc} */ public function __toString() { $attribute = $this->namespace ? $this->namespace.'|'.$this->attribute : $this->attribute; return 'exists' === $this->operator ? sprintf('%s[%s[%s]]', $this->getNodeName(), $this->selector, $attribute) : sprintf("%s[%s[%s %s '%s']]", $this->getNodeName(), $this->selector, $attribute, $this->operator, $this->value); } } PK] iCssSelector/Node/ClassNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "." node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class ClassNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $name; /** * @param NodeInterface $selector * @param string $name */ public function __construct(NodeInterface $selector, $name) { $this->selector = $selector; $this->name = $name; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getName() { return $this->name; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } /** * {@inheritdoc} */ public function __toString() { return sprintf('%s[%s.%s]', $this->getNodeName(), $this->selector, $this->name); } } PK]bb!CssSelector/Node/NegationNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a ":not()" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class NegationNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var NodeInterface */ private $subSelector; /** * @param NodeInterface $selector * @param NodeInterface $subSelector */ public function __construct(NodeInterface $selector, NodeInterface $subSelector) { $this->selector = $selector; $this->subSelector = $subSelector; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return NodeInterface */ public function getSubSelector() { return $this->subSelector; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); } /** * {@inheritdoc} */ public function __toString() { return sprintf('%s[%s:not(%s)]', $this->getNodeName(), $this->selector, $this->subSelector); } } PK].22CssSelector/Node/PseudoNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a ":" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class PseudoNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $identifier; /** * @param NodeInterface $selector * @param string $identifier */ public function __construct(NodeInterface $selector, $identifier) { $this->selector = $selector; $this->identifier = strtolower($identifier); } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getIdentifier() { return $this->identifier; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } /** * {@inheritdoc} */ public function __toString() { return sprintf('%s[%s:%s]', $this->getNodeName(), $this->selector, $this->identifier); } } PK]rI"CssSelector/Node/NodeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Interface for nodes. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface NodeInterface { /** * Returns node's name. * * @return string */ public function getNodeName(); /** * Returns node's specificity. * * @return Specificity */ public function getSpecificity(); /** * Returns node's string representation. * * @return string */ public function __toString(); } PK]uUUCssSelector/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator node extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class NodeExtension extends AbstractExtension { const ELEMENT_NAME_IN_LOWER_CASE = 1; const ATTRIBUTE_NAME_IN_LOWER_CASE = 2; const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4; /** * @var Translator */ private $translator; /** * @var int */ private $flags; /** * Constructor. * * @param Translator $translator * @param int $flags */ public function __construct(Translator $translator, $flags = 0) { $this->translator = $translator; $this->flags = $flags; } /** * @param int $flag * @param boolean $on * * @return NodeExtension */ public function setFlag($flag, $on) { if ($on && !$this->hasFlag($flag)) { $this->flags += $flag; } if (!$on && $this->hasFlag($flag)) { $this->flags -= $flag; } return $this; } /** * @param int $flag * * @return boolean */ public function hasFlag($flag) { return $this->flags & $flag; } /** * {@inheritdoc} */ public function getNodeTranslators() { return array( 'Selector' => array($this, 'translateSelector'), 'CombinedSelector' => array($this, 'translateCombinedSelector'), 'Negation' => array($this, 'translateNegation'), 'Function' => array($this, 'translateFunction'), 'Pseudo' => array($this, 'translatePseudo'), 'Attribute' => array($this, 'translateAttribute'), 'Class' => array($this, 'translateClass'), 'Hash' => array($this, 'translateHash'), 'Element' => array($this, 'translateElement'), ); } /** * @param Node\SelectorNode $node * * @return XPathExpr */ public function translateSelector(Node\SelectorNode $node) { return $this->translator->nodeToXPath($node->getTree()); } /** * @param Node\CombinedSelectorNode $node * * @return XPathExpr */ public function translateCombinedSelector(Node\CombinedSelectorNode $node) { return $this->translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector()); } /** * @param Node\NegationNode $node * * @return XPathExpr */ public function translateNegation(Node\NegationNode $node) { $xpath = $this->translator->nodeToXPath($node->getSelector()); $subXpath = $this->translator->nodeToXPath($node->getSubSelector()); $subXpath->addNameTest(); if ($subXpath->getCondition()) { return $xpath->addCondition(sprintf('not(%s)', $subXpath->getCondition())); } return $xpath->addCondition('0'); } /** * @param Node\FunctionNode $node * * @return XPathExpr */ public function translateFunction(Node\FunctionNode $node) { $xpath = $this->translator->nodeToXPath($node->getSelector()); return $this->translator->addFunction($xpath, $node); } /** * @param Node\PseudoNode $node * * @return XPathExpr */ public function translatePseudo(Node\PseudoNode $node) { $xpath = $this->translator->nodeToXPath($node->getSelector()); return $this->translator->addPseudoClass($xpath, $node->getIdentifier()); } /** * @param Node\AttributeNode $node * * @return XPathExpr */ public function translateAttribute(Node\AttributeNode $node) { $name = $node->getAttribute(); $safe = $this->isSafeName($name); if ($this->hasFlag(self::ATTRIBUTE_NAME_IN_LOWER_CASE)) { $name = strtolower($name); } if ($node->getNamespace()) { $name = sprintf('%s:%s', $node->getNamespace(), $name); $safe = $safe && $this->isSafeName($node->getNamespace()); } $attribute = $safe ? '@'.$name : sprintf('attribute::*[name() = %s]', Translator::getXpathLiteral($name)); $value = $node->getValue(); $xpath = $this->translator->nodeToXPath($node->getSelector()); if ($this->hasFlag(self::ATTRIBUTE_VALUE_IN_LOWER_CASE)) { $value = strtolower($value); } return $this->translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value); } /** * @param Node\ClassNode $node * * @return XPathExpr */ public function translateClass(Node\ClassNode $node) { $xpath = $this->translator->nodeToXPath($node->getSelector()); return $this->translator->addAttributeMatching($xpath, '~=', '@class', $node->getName()); } /** * @param Node\HashNode $node * * @return XPathExpr */ public function translateHash(Node\HashNode $node) { $xpath = $this->translator->nodeToXPath($node->getSelector()); return $this->translator->addAttributeMatching($xpath, '=', '@id', $node->getId()); } /** * @param Node\ElementNode $node * * @return XPathExpr */ public function translateElement(Node\ElementNode $node) { $element = $node->getElement(); if ($this->hasFlag(self::ELEMENT_NAME_IN_LOWER_CASE)) { $element = strtolower($element); } if ($element) { $safe = $this->isSafeName($element); } else { $element = '*'; $safe = true; } if ($node->getNamespace()) { $element = sprintf('%s:%s', $node->getNamespace(), $element); $safe = $safe && $this->isSafeName($node->getNamespace()); } $xpath = new XPathExpr('', $element); if (!$safe) { $xpath->addNameTest(); } return $xpath; } /** * {@inheritdoc} */ public function getName() { return 'node'; } /** * Tests if given name is safe. * * @param string $name * * @return boolean */ private function isSafeName($name) { return 0 < preg_match('~^[a-zA-Z_][a-zA-Z0-9_.-]*$~', $name); } } PK] 4CssSelector/XPath/Extension/PseudoClassExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator pseudo-class extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class PseudoClassExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getPseudoClassTranslators() { return array( 'root' => array($this, 'translateRoot'), 'first-child' => array($this, 'translateFirstChild'), 'last-child' => array($this, 'translateLastChild'), 'first-of-type' => array($this, 'translateFirstOfType'), 'last-of-type' => array($this, 'translateLastOfType'), 'only-child' => array($this, 'translateOnlyChild'), 'only-of-type' => array($this, 'translateOnlyOfType'), 'empty' => array($this, 'translateEmpty'), ); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateRoot(XPathExpr $xpath) { return $xpath->addCondition('not(parent::*)'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateFirstChild(XPathExpr $xpath) { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('position() = 1'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateLastChild(XPathExpr $xpath) { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('position() = last()'); } /** * @param XPathExpr $xpath * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateFirstOfType(XPathExpr $xpath) { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:first-of-type" is not implemented.'); } return $xpath ->addStarPrefix() ->addCondition('position() = 1'); } /** * @param XPathExpr $xpath * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateLastOfType(XPathExpr $xpath) { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:last-of-type" is not implemented.'); } return $xpath ->addStarPrefix() ->addCondition('position() = last()'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateOnlyChild(XPathExpr $xpath) { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('last() = 1'); } /** * @param XPathExpr $xpath * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateOnlyOfType(XPathExpr $xpath) { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:only-of-type" is not implemented.'); } return $xpath->addCondition('last() = 1'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateEmpty(XPathExpr $xpath) { return $xpath->addCondition('not(*) and not(string-length())'); } /** * {@inheritdoc} */ public function getName() { return 'pseudo-class'; } } PK]$pBB-CssSelector/XPath/Extension/HtmlExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator HTML extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class HtmlExtension extends AbstractExtension { /** * Constructor. * * @param Translator $translator */ public function __construct(Translator $translator) { $translator ->getExtension('node') ->setFlag(NodeExtension::ELEMENT_NAME_IN_LOWER_CASE, true) ->setFlag(NodeExtension::ATTRIBUTE_NAME_IN_LOWER_CASE, true); } /** * {@inheritdoc} */ public function getPseudoClassTranslators() { return array( 'checked' => array($this, 'translateChecked'), 'link' => array($this, 'translateLink'), 'disabled' => array($this, 'translateDisabled'), 'enabled' => array($this, 'translateEnabled'), 'selected' => array($this, 'translateSelected'), 'invalid' => array($this, 'translateInvalid'), 'hover' => array($this, 'translateHover'), 'visited' => array($this, 'translateVisited'), ); } /** * {@inheritdoc} */ public function getFunctionTranslators() { return array( 'lang' => array($this, 'translateLang'), ); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateChecked(XPathExpr $xpath) { return $xpath->addCondition( '(@checked ' ."and (name(.) = 'input' or name(.) = 'command')" ."and (@type = 'checkbox' or @type = 'radio'))" ); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateLink(XPathExpr $xpath) { return $xpath->addCondition("@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')"); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateDisabled(XPathExpr $xpath) { return $xpath->addCondition( "(" ."@disabled and" ."(" ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" ." or name(.) = 'command'" ." or name(.) = 'fieldset'" ." or name(.) = 'optgroup'" ." or name(.) = 'option'" .")" .") or (" ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" .")" ." and ancestor::fieldset[@disabled]" ); // todo: in the second half, add "and is not a descendant of that fieldset element's first legend element child, if any." } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateEnabled(XPathExpr $xpath) { return $xpath->addCondition( '(' .'@href and (' ."name(.) = 'a'" ." or name(.) = 'link'" ." or name(.) = 'area'" .')' .') or (' .'(' ."name(.) = 'command'" ." or name(.) = 'fieldset'" ." or name(.) = 'optgroup'" .')' .' and not(@disabled)' .') or (' .'(' ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" ." or name(.) = 'keygen'" .')' ." and not (@disabled or ancestor::fieldset[@disabled])" .') or (' ."name(.) = 'option' and not(" ."@disabled or ancestor::optgroup[@disabled]" .')' .')' ); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateLang(XPathExpr $xpath, FunctionNode $function) { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException( 'Expected a single string or identifier for :lang(), got ' .implode(', ', $arguments) ); } } return $xpath->addCondition(sprintf( 'ancestor-or-self::*[@lang][1][starts-with(concat(' ."translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-')" .', %s)]', 'lang', Translator::getXpathLiteral(strtolower($arguments[0]->getValue()).'-') )); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateSelected(XPathExpr $xpath) { return $xpath->addCondition("(@selected and name(.) = 'option')"); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateInvalid(XPathExpr $xpath) { return $xpath->addCondition('0'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateHover(XPathExpr $xpath) { return $xpath->addCondition('0'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateVisited(XPathExpr $xpath) { return $xpath->addCondition('0'); } /** * {@inheritdoc} */ public function getName() { return 'html'; } } PK]c-1CssSelector/XPath/Extension/AbstractExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; /** * XPath expression translator abstract extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ abstract class AbstractExtension implements ExtensionInterface { /** * {@inheritdoc} */ public function getNodeTranslators() { return array(); } /** * {@inheritdoc} */ public function getCombinationTranslators() { return array(); } /** * {@inheritdoc} */ public function getFunctionTranslators() { return array(); } /** * {@inheritdoc} */ public function getPseudoClassTranslators() { return array(); } /** * {@inheritdoc} */ public function getAttributeMatchingTranslators() { return array(); } } PK]܍:CssSelector/XPath/Extension/AttributeMatchingExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator attribute extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class AttributeMatchingExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getAttributeMatchingTranslators() { return array( 'exists' => array($this, 'translateExists'), '=' => array($this, 'translateEquals'), '~=' => array($this, 'translateIncludes'), '|=' => array($this, 'translateDashMatch'), '^=' => array($this, 'translatePrefixMatch'), '$=' => array($this, 'translateSuffixMatch'), '*=' => array($this, 'translateSubstringMatch'), '!=' => array($this, 'translateDifferent'), ); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateExists(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition($attribute); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateEquals(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition(sprintf('%s = %s', $attribute, Translator::getXpathLiteral($value))); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateIncludes(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition($value ? sprintf( '%1$s and contains(concat(\' \', normalize-space(%1$s), \' \'), %2$s)', $attribute, Translator::getXpathLiteral(' '.$value.' ') ) : '0'); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateDashMatch(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition(sprintf( '%1$s and (%1$s = %2$s or starts-with(%1$s, %3$s))', $attribute, Translator::getXpathLiteral($value), Translator::getXpathLiteral($value.'-') )); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translatePrefixMatch(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition($value ? sprintf( '%1$s and starts-with(%1$s, %2$s)', $attribute, Translator::getXpathLiteral($value) ) : '0'); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateSuffixMatch(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition($value ? sprintf( '%1$s and substring(%1$s, string-length(%1$s)-%2$s) = %3$s', $attribute, strlen($value) - 1, Translator::getXpathLiteral($value) ) : '0'); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateSubstringMatch(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition($value ? sprintf( '%1$s and contains(%1$s, %2$s)', $attribute, Translator::getXpathLiteral($value) ) : '0'); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateDifferent(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition(sprintf( $value ? 'not(%1$s) or %1$s != %2$s' : '%s != %s', $attribute, Translator::getXpathLiteral($value) )); } /** * {@inheritdoc} */ public function getName() { return 'attribute-matching'; } } PK]u1CssSelector/XPath/Extension/FunctionExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\Parser\Parser; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator function extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class FunctionExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getFunctionTranslators() { return array( 'nth-child' => array($this, 'translateNthChild'), 'nth-last-child' => array($this, 'translateNthLastChild'), 'nth-of-type' => array($this, 'translateNthOfType'), 'nth-last-of-type' => array($this, 'translateNthLastOfType'), 'contains' => array($this, 'translateContains'), 'lang' => array($this, 'translateLang'), ); } /** * @param XPathExpr $xpath * @param FunctionNode $function * @param boolean $last * @param boolean $addNameTest * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateNthChild(XPathExpr $xpath, FunctionNode $function, $last = false, $addNameTest = true) { try { list($a, $b) = Parser::parseSeries($function->getArguments()); } catch (SyntaxErrorException $e) { throw new ExpressionErrorException(sprintf('Invalid series: %s', implode(', ', $function->getArguments())), 0, $e); } $xpath->addStarPrefix(); if ($addNameTest) { $xpath->addNameTest(); } if (0 === $a) { return $xpath->addCondition('position() = '.($last ? 'last() - '.($b - 1) : $b)); } if ($a < 0) { if ($b < 1) { return $xpath->addCondition('false()'); } $sign = '<='; } else { $sign = '>='; } $expr = 'position()'; if ($last) { $expr = 'last() - '.$expr; $b--; } if (0 !== $b) { $expr .= ' - '.$b; } $conditions = array(sprintf('%s %s 0', $expr, $sign)); if (1 !== $a && -1 !== $a) { $conditions[] = sprintf('(%s) mod %d = 0', $expr, $a); } return $xpath->addCondition(implode(' and ', $conditions)); // todo: handle an+b, odd, even // an+b means every-a, plus b, e.g., 2n+1 means odd // 0n+b means b // n+0 means a=1, i.e., all elements // an means every a elements, i.e., 2n means even // -n means -1n // -1n+6 means elements 6 and previous } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr */ public function translateNthLastChild(XPathExpr $xpath, FunctionNode $function) { return $this->translateNthChild($xpath, $function, true); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr */ public function translateNthOfType(XPathExpr $xpath, FunctionNode $function) { return $this->translateNthChild($xpath, $function, false, false); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateNthLastOfType(XPathExpr $xpath, FunctionNode $function) { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:nth-of-type()" is not implemented.'); } return $this->translateNthChild($xpath, $function, true, false); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateContains(XPathExpr $xpath, FunctionNode $function) { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException( 'Expected a single string or identifier for :contains(), got ' .implode(', ', $arguments) ); } } return $xpath->addCondition(sprintf( 'contains(string(.), %s)', Translator::getXpathLiteral($arguments[0]->getValue()) )); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateLang(XPathExpr $xpath, FunctionNode $function) { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException( 'Expected a single string or identifier for :lang(), got ' .implode(', ', $arguments) ); } } return $xpath->addCondition(sprintf( 'lang(%s)', Translator::getXpathLiteral($arguments[0]->getValue()) )); } /** * {@inheritdoc} */ public function getName() { return 'function'; } } PK]||2CssSelector/XPath/Extension/ExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; /** * XPath expression translator extension interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface ExtensionInterface { /** * Returns node translators. * * @return callable[] */ public function getNodeTranslators(); /** * Returns combination translators. * * @return callable[] */ public function getCombinationTranslators(); /** * Returns function translators. * * @return callable[] */ public function getFunctionTranslators(); /** * Returns pseudo-class translators. * * @return callable[] */ public function getPseudoClassTranslators(); /** * Returns attribute operation translators. * * @return callable[] */ public function getAttributeMatchingTranslators(); /** * Returns extension name. * * @return string */ public function getName(); } PK]x= = 4CssSelector/XPath/Extension/CombinationExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator combination extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class CombinationExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getCombinationTranslators() { return array( ' ' => array($this, 'translateDescendant'), '>' => array($this, 'translateChild'), '+' => array($this, 'translateDirectAdjacent'), '~' => array($this, 'translateIndirectAdjacent'), ); } /** * @param XPathExpr $xpath * @param XPathExpr $combinedXpath * * @return XPathExpr */ public function translateDescendant(XPathExpr $xpath, XPathExpr $combinedXpath) { return $xpath->join('/descendant-or-self::*/', $combinedXpath); } /** * @param XPathExpr $xpath * @param XPathExpr $combinedXpath * * @return XPathExpr */ public function translateChild(XPathExpr $xpath, XPathExpr $combinedXpath) { return $xpath->join('/', $combinedXpath); } /** * @param XPathExpr $xpath * @param XPathExpr $combinedXpath * * @return XPathExpr */ public function translateDirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath) { return $xpath ->join('/following-sibling::', $combinedXpath) ->addNameTest() ->addCondition('position() = 1'); } /** * @param XPathExpr $xpath * @param XPathExpr $combinedXpath * * @return XPathExpr */ public function translateIndirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath) { return $xpath->join('/following-sibling::', $combinedXpath); } /** * {@inheritdoc} */ public function getName() { return 'combination'; } } PK]r7 7 CssSelector/XPath/XPathExpr.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; /** * XPath expression translator interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class XPathExpr { /** * @var string */ private $path; /** * @var string */ private $element; /** * @var string */ private $condition; /** * @param string $path * @param string $element * @param string $condition * @param boolean $starPrefix */ public function __construct($path = '', $element = '*', $condition = '', $starPrefix = false) { $this->path = $path; $this->element = $element; $this->condition = $condition; if ($starPrefix) { $this->addStarPrefix(); } } /** * @return string */ public function getElement() { return $this->element; } /** * @param $condition * * @return XPathExpr */ public function addCondition($condition) { $this->condition = $this->condition ? sprintf('%s and (%s)', $this->condition, $condition) : $condition; return $this; } /** * @return string */ public function getCondition() { return $this->condition; } /** * @return XPathExpr */ public function addNameTest() { if ('*' !== $this->element) { $this->addCondition('name() = '.Translator::getXpathLiteral($this->element)); $this->element = '*'; } return $this; } /** * @return XPathExpr */ public function addStarPrefix() { $this->path .= '*/'; return $this; } /** * Joins another XPathExpr with a combiner. * * @param string $combiner * @param XPathExpr $expr * * @return XPathExpr */ public function join($combiner, XPathExpr $expr) { $path = $this->__toString().$combiner; if ('*/' !== $expr->path) { $path .= $expr->path; } $this->path = $path; $this->element = $expr->element; $this->condition = $expr->condition; return $this; } /** * @return string */ public function __toString() { $path = $this->path.$this->element; $condition = null === $this->condition || '' === $this->condition ? '' : '['.$this->condition.']'; return $path.$condition; } } PK]!! CssSelector/XPath/Translator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\Node\NodeInterface; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\Parser; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * XPath expression translator interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class Translator implements TranslatorInterface { /** * @var ParserInterface */ private $mainParser; /** * @var ParserInterface[] */ private $shortcutParsers = array(); /** * @var Extension\ExtensionInterface */ private $extensions = array(); /** * @var array */ private $nodeTranslators = array(); /** * @var array */ private $combinationTranslators = array(); /** * @var array */ private $functionTranslators = array(); /** * @var array */ private $pseudoClassTranslators = array(); /** * @var array */ private $attributeMatchingTranslators = array(); /** * Constructor. */ public function __construct(ParserInterface $parser = null) { $this->mainParser = $parser ?: new Parser(); $this ->registerExtension(new Extension\NodeExtension($this)) ->registerExtension(new Extension\CombinationExtension()) ->registerExtension(new Extension\FunctionExtension()) ->registerExtension(new Extension\PseudoClassExtension()) ->registerExtension(new Extension\AttributeMatchingExtension()) ; } /** * @param string $element * * @return string */ public static function getXpathLiteral($element) { if (false === strpos($element, "'")) { return "'".$element."'"; } if (false === strpos($element, '"')) { return '"'.$element.'"'; } $string = $element; $parts = array(); while (true) { if (false !== $pos = strpos($string, "'")) { $parts[] = sprintf("'%s'", substr($string, 0, $pos)); $parts[] = "\"'\""; $string = substr($string, $pos + 1); } else { $parts[] = "'$string'"; break; } } return sprintf('concat(%s)', implode($parts, ', ')); } /** * {@inheritdoc} */ public function cssToXPath($cssExpr, $prefix = 'descendant-or-self::') { $selectors = $this->parseSelectors($cssExpr); /** @var SelectorNode $selector */ foreach ($selectors as $selector) { if (null !== $selector->getPseudoElement()) { throw new ExpressionErrorException('Pseudo-elements are not supported.'); } } $translator = $this; return implode(' | ', array_map(function (SelectorNode $selector) use ($translator, $prefix) { return $translator->selectorToXPath($selector, $prefix); }, $selectors)); } /** * {@inheritdoc} */ public function selectorToXPath(SelectorNode $selector, $prefix = 'descendant-or-self::') { return ($prefix ?: '').$this->nodeToXPath($selector); } /** * Registers an extension. * * @param Extension\ExtensionInterface $extension * * @return Translator */ public function registerExtension(Extension\ExtensionInterface $extension) { $this->extensions[$extension->getName()] = $extension; $this->nodeTranslators = array_merge($this->nodeTranslators, $extension->getNodeTranslators()); $this->combinationTranslators = array_merge($this->combinationTranslators, $extension->getCombinationTranslators()); $this->functionTranslators = array_merge($this->functionTranslators, $extension->getFunctionTranslators()); $this->pseudoClassTranslators = array_merge($this->pseudoClassTranslators, $extension->getPseudoClassTranslators()); $this->attributeMatchingTranslators = array_merge($this->attributeMatchingTranslators, $extension->getAttributeMatchingTranslators()); return $this; } /** * @param string $name * * @return Extension\ExtensionInterface * * @throws ExpressionErrorException */ public function getExtension($name) { if (!isset($this->extensions[$name])) { throw new ExpressionErrorException(sprintf('Extension "%s" not registered.', $name)); } return $this->extensions[$name]; } /** * Registers a shortcut parser. * * @param ParserInterface $shortcut * * @return Translator */ public function registerParserShortcut(ParserInterface $shortcut) { $this->shortcutParsers[] = $shortcut; return $this; } /** * @param NodeInterface $node * * @return XPathExpr * * @throws ExpressionErrorException */ public function nodeToXPath(NodeInterface $node) { if (!isset($this->nodeTranslators[$node->getNodeName()])) { throw new ExpressionErrorException(sprintf('Node "%s" not supported.', $node->getNodeName())); } return call_user_func($this->nodeTranslators[$node->getNodeName()], $node); } /** * @param string $combiner * @param NodeInterface $xpath * @param NodeInterface $combinedXpath * * @return XPathExpr * * @throws ExpressionErrorException */ public function addCombination($combiner, NodeInterface $xpath, NodeInterface $combinedXpath) { if (!isset($this->combinationTranslators[$combiner])) { throw new ExpressionErrorException(sprintf('Combiner "%s" not supported.', $combiner)); } return call_user_func($this->combinationTranslators[$combiner], $this->nodeToXPath($xpath), $this->nodeToXPath($combinedXpath)); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr * * @throws ExpressionErrorException */ public function addFunction(XPathExpr $xpath, FunctionNode $function) { if (!isset($this->functionTranslators[$function->getName()])) { throw new ExpressionErrorException(sprintf('Function "%s" not supported.', $function->getName())); } return call_user_func($this->functionTranslators[$function->getName()], $xpath, $function); } /** * @param XPathExpr $xpath * @param string $pseudoClass * * @return XPathExpr * * @throws ExpressionErrorException */ public function addPseudoClass(XPathExpr $xpath, $pseudoClass) { if (!isset($this->pseudoClassTranslators[$pseudoClass])) { throw new ExpressionErrorException(sprintf('Pseudo-class "%s" not supported.', $pseudoClass)); } return call_user_func($this->pseudoClassTranslators[$pseudoClass], $xpath); } /** * @param XPathExpr $xpath * @param string $operator * @param string $attribute * @param string $value * * @throws ExpressionErrorException * * @return XPathExpr */ public function addAttributeMatching(XPathExpr $xpath, $operator, $attribute, $value) { if (!isset($this->attributeMatchingTranslators[$operator])) { throw new ExpressionErrorException(sprintf('Attribute matcher operator "%s" not supported.', $operator)); } return call_user_func($this->attributeMatchingTranslators[$operator], $xpath, $attribute, $value); } /** * @param string $css * * @return SelectorNode[] */ private function parseSelectors($css) { foreach ($this->shortcutParsers as $shortcut) { $tokens = $shortcut->parse($css); if (!empty($tokens)) { return $tokens; } } return $this->mainParser->parse($css); } } PK] )CssSelector/XPath/TranslatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; use Symfony\Component\CssSelector\Node\SelectorNode; /** * XPath expression translator interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface TranslatorInterface { /** * Translates a CSS selector to an XPath expression. * * @param string $cssExpr * @param string $prefix * * @return XPathExpr */ public function cssToXPath($cssExpr, $prefix = 'descendant-or-self::'); /** * Translates a parsed selector node to an XPath expression * * @param SelectorNode $selector * @param string $prefix * * @return XPathExpr */ public function selectorToXPath(SelectorNode $selector, $prefix = 'descendant-or-self::'); } PK]EYHttpFoundation/HeaderBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * HeaderBag is a container for HTTP headers. * * @author Fabien Potencier * * @api */ class HeaderBag implements \IteratorAggregate, \Countable { protected $headers = array(); protected $cacheControl = array(); /** * Constructor. * * @param array $headers An array of HTTP headers * * @api */ public function __construct(array $headers = array()) { foreach ($headers as $key => $values) { $this->set($key, $values); } } /** * Returns the headers as a string. * * @return string The headers */ public function __toString() { if (!$this->headers) { return ''; } $max = max(array_map('strlen', array_keys($this->headers))) + 1; $content = ''; ksort($this->headers); foreach ($this->headers as $name => $values) { $name = implode('-', array_map('ucfirst', explode('-', $name))); foreach ($values as $value) { $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value); } } return $content; } /** * Returns the headers. * * @return array An array of headers * * @api */ public function all() { return $this->headers; } /** * Returns the parameter keys. * * @return array An array of parameter keys * * @api */ public function keys() { return array_keys($this->headers); } /** * Replaces the current HTTP headers by a new set. * * @param array $headers An array of HTTP headers * * @api */ public function replace(array $headers = array()) { $this->headers = array(); $this->add($headers); } /** * Adds new headers the current HTTP headers set. * * @param array $headers An array of HTTP headers * * @api */ public function add(array $headers) { foreach ($headers as $key => $values) { $this->set($key, $values); } } /** * Returns a header value by name. * * @param string $key The header name * @param mixed $default The default value * @param Boolean $first Whether to return the first value or all header values * * @return string|array The first header value if $first is true, an array of values otherwise * * @api */ public function get($key, $default = null, $first = true) { $key = strtr(strtolower($key), '_', '-'); if (!array_key_exists($key, $this->headers)) { if (null === $default) { return $first ? null : array(); } return $first ? $default : array($default); } if ($first) { return count($this->headers[$key]) ? $this->headers[$key][0] : $default; } return $this->headers[$key]; } /** * Sets a header by name. * * @param string $key The key * @param string|array $values The value or an array of values * @param Boolean $replace Whether to replace the actual value or not (true by default) * * @api */ public function set($key, $values, $replace = true) { $key = strtr(strtolower($key), '_', '-'); $values = array_values((array) $values); if (true === $replace || !isset($this->headers[$key])) { $this->headers[$key] = $values; } else { $this->headers[$key] = array_merge($this->headers[$key], $values); } if ('cache-control' === $key) { $this->cacheControl = $this->parseCacheControl($values[0]); } } /** * Returns true if the HTTP header is defined. * * @param string $key The HTTP header * * @return Boolean true if the parameter exists, false otherwise * * @api */ public function has($key) { return array_key_exists(strtr(strtolower($key), '_', '-'), $this->headers); } /** * Returns true if the given HTTP header contains the given value. * * @param string $key The HTTP header name * @param string $value The HTTP value * * @return Boolean true if the value is contained in the header, false otherwise * * @api */ public function contains($key, $value) { return in_array($value, $this->get($key, null, false)); } /** * Removes a header. * * @param string $key The HTTP header name * * @api */ public function remove($key) { $key = strtr(strtolower($key), '_', '-'); unset($this->headers[$key]); if ('cache-control' === $key) { $this->cacheControl = array(); } } /** * Returns the HTTP header value converted to a date. * * @param string $key The parameter key * @param \DateTime $default The default value * * @return null|\DateTime The parsed DateTime or the default value if the header does not exist * * @throws \RuntimeException When the HTTP header is not parseable * * @api */ public function getDate($key, \DateTime $default = null) { if (null === $value = $this->get($key)) { return $default; } if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) { throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value)); } return $date; } public function addCacheControlDirective($key, $value = true) { $this->cacheControl[$key] = $value; $this->set('Cache-Control', $this->getCacheControlHeader()); } public function hasCacheControlDirective($key) { return array_key_exists($key, $this->cacheControl); } public function getCacheControlDirective($key) { return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null; } public function removeCacheControlDirective($key) { unset($this->cacheControl[$key]); $this->set('Cache-Control', $this->getCacheControlHeader()); } /** * Returns an iterator for headers. * * @return \ArrayIterator An \ArrayIterator instance */ public function getIterator() { return new \ArrayIterator($this->headers); } /** * Returns the number of headers. * * @return int The number of headers */ public function count() { return count($this->headers); } protected function getCacheControlHeader() { $parts = array(); ksort($this->cacheControl); foreach ($this->cacheControl as $key => $value) { if (true === $value) { $parts[] = $key; } else { if (preg_match('#[^a-zA-Z0-9._-]#', $value)) { $value = '"'.$value.'"'; } $parts[] = "$key=$value"; } } return implode(', ', $parts); } /** * Parses a Cache-Control HTTP header. * * @param string $header The value of the Cache-Control HTTP header * * @return array An array representing the attribute values */ protected function parseCacheControl($header) { $cacheControl = array(); preg_match_all('#([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?#', $header, $matches, PREG_SET_ORDER); foreach ($matches as $match) { $cacheControl[strtolower($match[1])] = isset($match[3]) ? $match[3] : (isset($match[2]) ? $match[2] : true); } return $cacheControl; } } PK]?` y y :HttpFoundation/Resources/stubs/SessionHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * SessionHandlerInterface * * Provides forward compatibility with PHP 5.4 * * Extensive documentation can be found at php.net, see links: * * @see http://php.net/sessionhandlerinterface * @see http://php.net/session.customhandler * @see http://php.net/session-set-save-handler * * @author Drak */ interface SessionHandlerInterface { /** * Open session. * * @see http://php.net/sessionhandlerinterface.open * * @param string $savePath Save path. * @param string $sessionName Session Name. * * @throws \RuntimeException If something goes wrong starting the session. * * @return boolean */ public function open($savePath, $sessionName); /** * Close session. * * @see http://php.net/sessionhandlerinterface.close * * @return boolean */ public function close(); /** * Read session. * * @param string $sessionId * * @see http://php.net/sessionhandlerinterface.read * * @throws \RuntimeException On fatal error but not "record not found". * * @return string String as stored in persistent storage or empty string in all other cases. */ public function read($sessionId); /** * Commit session to storage. * * @see http://php.net/sessionhandlerinterface.write * * @param string $sessionId Session ID. * @param string $data Session serialized data to save. * * @return boolean */ public function write($sessionId, $data); /** * Destroys this session. * * @see http://php.net/sessionhandlerinterface.destroy * * @param string $sessionId Session ID. * * @throws \RuntimeException On fatal error. * * @return boolean */ public function destroy($sessionId); /** * Garbage collection for storage. * * @see http://php.net/sessionhandlerinterface.gc * * @param integer $lifetime Max lifetime in seconds to keep sessions stored. * * @throws \RuntimeException On fatal error. * * @return boolean */ public function gc($lifetime); } PK]ݣ""$HttpFoundation/ResponseHeaderBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * ResponseHeaderBag is a container for Response HTTP headers. * * @author Fabien Potencier * * @api */ class ResponseHeaderBag extends HeaderBag { const COOKIES_FLAT = 'flat'; const COOKIES_ARRAY = 'array'; const DISPOSITION_ATTACHMENT = 'attachment'; const DISPOSITION_INLINE = 'inline'; /** * @var array */ protected $computedCacheControl = array(); /** * @var array */ protected $cookies = array(); /** * @var array */ protected $headerNames = array(); /** * Constructor. * * @param array $headers An array of HTTP headers * * @api */ public function __construct(array $headers = array()) { parent::__construct($headers); if (!isset($this->headers['cache-control'])) { $this->set('Cache-Control', ''); } } /** * {@inheritdoc} */ public function __toString() { $cookies = ''; foreach ($this->getCookies() as $cookie) { $cookies .= 'Set-Cookie: '.$cookie."\r\n"; } ksort($this->headerNames); return parent::__toString().$cookies; } /** * Returns the headers, with original capitalizations. * * @return array An array of headers */ public function allPreserveCase() { return array_combine($this->headerNames, $this->headers); } /** * {@inheritdoc} * * @api */ public function replace(array $headers = array()) { $this->headerNames = array(); parent::replace($headers); if (!isset($this->headers['cache-control'])) { $this->set('Cache-Control', ''); } } /** * {@inheritdoc} * * @api */ public function set($key, $values, $replace = true) { parent::set($key, $values, $replace); $uniqueKey = strtr(strtolower($key), '_', '-'); $this->headerNames[$uniqueKey] = $key; // ensure the cache-control header has sensible defaults if (in_array($uniqueKey, array('cache-control', 'etag', 'last-modified', 'expires'))) { $computed = $this->computeCacheControlValue(); $this->headers['cache-control'] = array($computed); $this->headerNames['cache-control'] = 'Cache-Control'; $this->computedCacheControl = $this->parseCacheControl($computed); } } /** * {@inheritdoc} * * @api */ public function remove($key) { parent::remove($key); $uniqueKey = strtr(strtolower($key), '_', '-'); unset($this->headerNames[$uniqueKey]); if ('cache-control' === $uniqueKey) { $this->computedCacheControl = array(); } } /** * {@inheritdoc} */ public function hasCacheControlDirective($key) { return array_key_exists($key, $this->computedCacheControl); } /** * {@inheritdoc} */ public function getCacheControlDirective($key) { return array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null; } /** * Sets a cookie. * * @param Cookie $cookie * * @api */ public function setCookie(Cookie $cookie) { $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie; } /** * Removes a cookie from the array, but does not unset it in the browser * * @param string $name * @param string $path * @param string $domain * * @api */ public function removeCookie($name, $path = '/', $domain = null) { if (null === $path) { $path = '/'; } unset($this->cookies[$domain][$path][$name]); if (empty($this->cookies[$domain][$path])) { unset($this->cookies[$domain][$path]); if (empty($this->cookies[$domain])) { unset($this->cookies[$domain]); } } } /** * Returns an array with all cookies * * @param string $format * * @throws \InvalidArgumentException When the $format is invalid * * @return array * * @api */ public function getCookies($format = self::COOKIES_FLAT) { if (!in_array($format, array(self::COOKIES_FLAT, self::COOKIES_ARRAY))) { throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', array(self::COOKIES_FLAT, self::COOKIES_ARRAY)))); } if (self::COOKIES_ARRAY === $format) { return $this->cookies; } $flattenedCookies = array(); foreach ($this->cookies as $path) { foreach ($path as $cookies) { foreach ($cookies as $cookie) { $flattenedCookies[] = $cookie; } } } return $flattenedCookies; } /** * Clears a cookie in the browser * * @param string $name * @param string $path * @param string $domain * * @api */ public function clearCookie($name, $path = '/', $domain = null) { $this->setCookie(new Cookie($name, null, 1, $path, $domain)); } /** * Generates a HTTP Content-Disposition field-value. * * @param string $disposition One of "inline" or "attachment" * @param string $filename A unicode string * @param string $filenameFallback A string containing only ASCII characters that * is semantically equivalent to $filename. If the filename is already ASCII, * it can be omitted, or just copied from $filename * * @return string A string suitable for use as a Content-Disposition field-value. * * @throws \InvalidArgumentException * @see RFC 6266 */ public function makeDisposition($disposition, $filename, $filenameFallback = '') { if (!in_array($disposition, array(self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE))) { throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); } if ('' == $filenameFallback) { $filenameFallback = $filename; } // filenameFallback is not ASCII. if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); } // percent characters aren't safe in fallback. if (false !== strpos($filenameFallback, '%')) { throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); } // path separators aren't allowed in either. if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) { throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); } $output = sprintf('%s; filename="%s"', $disposition, str_replace('"', '\\"', $filenameFallback)); if ($filename !== $filenameFallback) { $output .= sprintf("; filename*=utf-8''%s", rawurlencode($filename)); } return $output; } /** * Returns the calculated value of the cache-control header. * * This considers several other headers and calculates or modifies the * cache-control header to a sensible, conservative value. * * @return string */ protected function computeCacheControlValue() { if (!$this->cacheControl && !$this->has('ETag') && !$this->has('Last-Modified') && !$this->has('Expires')) { return 'no-cache'; } if (!$this->cacheControl) { // conservative by default return 'private, must-revalidate'; } $header = $this->getCacheControlHeader(); if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) { return $header; } // public if s-maxage is defined, private otherwise if (!isset($this->cacheControl['s-maxage'])) { return $header.', private'; } return $header; } } PK]zu00:HttpFoundation/Session/Storage/PhpBridgeSessionStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; /** * Allows session to be started by PHP and managed by Symfony2 * * @author Drak */ class PhpBridgeSessionStorage extends NativeSessionStorage { /** * Constructor. * * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler * @param MetadataBag $metaBag MetadataBag */ public function __construct($handler = null, MetadataBag $metaBag = null) { $this->setMetadataBag($metaBag); $this->setSaveHandler($handler); } /** * {@inheritdoc} */ public function start() { if ($this->started && !$this->closed) { return true; } $this->loadSession(); if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { // This condition matches only PHP 5.3 + internal save handlers $this->saveHandler->setActive(true); } return true; } /** * {@inheritdoc} */ public function clear() { // clear out the bags and nothing else that may be set // since the purpose of this driver is to share a handler foreach ($this->bags as $bag) { $bag->clear(); } // reconnect the bags to the session $this->loadSession(); } } PK]$  9HttpFoundation/Session/Storage/MockFileSessionStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; /** * MockFileSessionStorage is used to mock sessions for * functional testing when done in a single PHP process. * * No PHP session is actually started since a session can be initialized * and shutdown only once per PHP execution cycle and this class does * not pollute any session related globals, including session_*() functions * or session.* PHP ini directives. * * @author Drak */ class MockFileSessionStorage extends MockArraySessionStorage { /** * @var string */ private $savePath; /** * Constructor. * * @param string $savePath Path of directory to save session files. * @param string $name Session name. * @param MetadataBag $metaBag MetadataBag instance. */ public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag $metaBag = null) { if (null === $savePath) { $savePath = sys_get_temp_dir(); } if (!is_dir($savePath)) { mkdir($savePath, 0777, true); } $this->savePath = $savePath; parent::__construct($name, $metaBag); } /** * {@inheritdoc} */ public function start() { if ($this->started) { return true; } if (!$this->id) { $this->id = $this->generateId(); } $this->read(); $this->started = true; return true; } /** * {@inheritdoc} */ public function regenerate($destroy = false, $lifetime = null) { if (!$this->started) { $this->start(); } if ($destroy) { $this->destroy(); } return parent::regenerate($destroy, $lifetime); } /** * {@inheritdoc} */ public function save() { if (!$this->started) { throw new \RuntimeException("Trying to save a session that was not started yet or was already closed"); } file_put_contents($this->getFilePath(), serialize($this->data)); // this is needed for Silex, where the session object is re-used across requests // in functional tests. In Symfony, the container is rebooted, so we don't have // this issue $this->started = false; } /** * Deletes a session from persistent storage. * Deliberately leaves session data in memory intact. */ private function destroy() { if (is_file($this->getFilePath())) { unlink($this->getFilePath()); } } /** * Calculate path to file. * * @return string File path */ private function getFilePath() { return $this->savePath.'/'.$this->id.'.mocksess'; } /** * Reads session from storage and loads session. */ private function read() { $filePath = $this->getFilePath(); $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : array(); $this->loadSession(); } } PK]2] 6HttpFoundation/Session/Storage/Proxy/AbstractProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; /** * AbstractProxy. * * @author Drak */ abstract class AbstractProxy { /** * Flag if handler wraps an internal PHP session handler (using \SessionHandler). * * @var boolean */ protected $wrapper = false; /** * @var boolean */ protected $active = false; /** * @var string */ protected $saveHandlerName; /** * Gets the session.save_handler name. * * @return string */ public function getSaveHandlerName() { return $this->saveHandlerName; } /** * Is this proxy handler and instance of \SessionHandlerInterface. * * @return boolean */ public function isSessionHandlerInterface() { return ($this instanceof \SessionHandlerInterface); } /** * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. * * @return Boolean */ public function isWrapper() { return $this->wrapper; } /** * Has a session started? * * @return Boolean */ public function isActive() { if (version_compare(phpversion(), '5.4.0', '>=')) { return $this->active = \PHP_SESSION_ACTIVE === session_status(); } return $this->active; } /** * Sets the active flag. * * Has no effect under PHP 5.4+ as status is detected * automatically in isActive() * * @internal * * @param Boolean $flag * * @throws \LogicException */ public function setActive($flag) { if (version_compare(phpversion(), '5.4.0', '>=')) { throw new \LogicException('This method is disabled in PHP 5.4.0+'); } $this->active = (bool) $flag; } /** * Gets the session ID. * * @return string */ public function getId() { return session_id(); } /** * Sets the session ID. * * @param string $id * * @throws \LogicException */ public function setId($id) { if ($this->isActive()) { throw new \LogicException('Cannot change the ID of an active session'); } session_id($id); } /** * Gets the session name. * * @return string */ public function getName() { return session_name(); } /** * Sets the session name. * * @param string $name * * @throws \LogicException */ public function setName($name) { if ($this->isActive()) { throw new \LogicException('Cannot change the name of an active session'); } session_name($name); } } PK]A4HttpFoundation/Session/Storage/Proxy/NativeProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; /** * NativeProxy. * * This proxy is built-in session handlers in PHP 5.3.x * * @author Drak */ class NativeProxy extends AbstractProxy { /** * Constructor. */ public function __construct() { // this makes an educated guess as to what the handler is since it should already be set. $this->saveHandlerName = ini_get('session.save_handler'); } /** * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. * * @return Boolean False. */ public function isWrapper() { return false; } } PK]mwȡ<HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; /** * SessionHandler proxy. * * @author Drak */ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface { /** * @var \SessionHandlerInterface */ protected $handler; /** * Constructor. * * @param \SessionHandlerInterface $handler */ public function __construct(\SessionHandlerInterface $handler) { $this->handler = $handler; $this->wrapper = ($handler instanceof \SessionHandler); $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user'; } // \SessionHandlerInterface /** * {@inheritdoc} */ public function open($savePath, $sessionName) { $return = (bool) $this->handler->open($savePath, $sessionName); if (true === $return) { $this->active = true; } return $return; } /** * {@inheritdoc} */ public function close() { $this->active = false; return (bool) $this->handler->close(); } /** * {@inheritdoc} */ public function read($id) { return (string) $this->handler->read($id); } /** * {@inheritdoc} */ public function write($id, $data) { return (bool) $this->handler->write($id, $data); } /** * {@inheritdoc} */ public function destroy($id) { return (bool) $this->handler->destroy($id); } /** * {@inheritdoc} */ public function gc($maxlifetime) { return (bool) $this->handler->gc($maxlifetime); } } PK]uY0CHttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * NativeFileSessionHandler. * * Native session handler using PHP's built in file storage. * * @author Drak */ class NativeFileSessionHandler extends NativeSessionHandler { /** * Constructor. * * @param string $savePath Path of directory to save session files. * Default null will leave setting as defined by PHP. * '/path', 'N;/path', or 'N;octal-mode;/path * * @see http://php.net/session.configuration.php#ini.session.save-path for further details. * * @throws \InvalidArgumentException On invalid $savePath */ public function __construct($savePath = null) { if (null === $savePath) { $savePath = ini_get('session.save_path'); } $baseDir = $savePath; if ($count = substr_count($savePath, ';')) { if ($count > 2) { throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'', $savePath)); } // characters after last ';' are the path $baseDir = ltrim(strrchr($savePath, ';'), ';'); } if ($baseDir && !is_dir($baseDir)) { mkdir($baseDir, 0777, true); } ini_set('session.save_path', $savePath); ini_set('session.save_handler', 'files'); } } PK]i@HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * MongoDB session handler * * @author Markus Bachmann */ class MongoDbSessionHandler implements \SessionHandlerInterface { /** * @var \Mongo */ private $mongo; /** * @var \MongoCollection */ private $collection; /** * @var array */ private $options; /** * Constructor. * * List of available options: * * database: The name of the database [required] * * collection: The name of the collection [required] * * id_field: The field name for storing the session id [default: _id] * * data_field: The field name for storing the session data [default: data] * * time_field: The field name for storing the timestamp [default: time] * * @param \Mongo|\MongoClient $mongo A MongoClient or Mongo instance * @param array $options An associative array of field options * * @throws \InvalidArgumentException When MongoClient or Mongo instance not provided * @throws \InvalidArgumentException When "database" or "collection" not provided */ public function __construct($mongo, array $options) { if (!($mongo instanceof \MongoClient || $mongo instanceof \Mongo)) { throw new \InvalidArgumentException('MongoClient or Mongo instance required'); } if (!isset($options['database']) || !isset($options['collection'])) { throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler'); } $this->mongo = $mongo; $this->options = array_merge(array( 'id_field' => '_id', 'data_field' => 'data', 'time_field' => 'time', ), $options); } /** * {@inheritDoc} */ public function open($savePath, $sessionName) { return true; } /** * {@inheritDoc} */ public function close() { return true; } /** * {@inheritDoc} */ public function destroy($sessionId) { $this->getCollection()->remove(array( $this->options['id_field'] => $sessionId )); return true; } /** * {@inheritDoc} */ public function gc($lifetime) { /* Note: MongoDB 2.2+ supports TTL collections, which may be used in * place of this method by indexing the "time_field" field with an * "expireAfterSeconds" option. Regardless of whether TTL collections * are used, consider indexing this field to make the remove query more * efficient. * * See: http://docs.mongodb.org/manual/tutorial/expire-data/ */ $time = new \MongoDate(time() - $lifetime); $this->getCollection()->remove(array( $this->options['time_field'] => array('$lt' => $time), )); return true; } /** * {@inheritDoc] */ public function write($sessionId, $data) { $this->getCollection()->update( array($this->options['id_field'] => $sessionId), array('$set' => array( $this->options['data_field'] => new \MongoBinData($data, \MongoBinData::BYTE_ARRAY), $this->options['time_field'] => new \MongoDate(), )), array('upsert' => true, 'multiple' => false) ); return true; } /** * {@inheritDoc} */ public function read($sessionId) { $dbData = $this->getCollection()->findOne(array( $this->options['id_field'] => $sessionId, )); return null === $dbData ? '' : $dbData[$this->options['data_field']]->bin; } /** * Return a "MongoCollection" instance * * @return \MongoCollection */ private function getCollection() { if (null === $this->collection) { $this->collection = $this->mongo->selectCollection($this->options['database'], $this->options['collection']); } return $this->collection; } /** * Return a Mongo instance * * @return \Mongo */ protected function getMongo() { return $this->mongo; } } PK]OZP""<HttpFoundation/Session/Storage/Handler/PdoSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * PdoSessionHandler. * * @author Fabien Potencier * @author Michael Williams */ class PdoSessionHandler implements \SessionHandlerInterface { /** * @var \PDO PDO instance. */ private $pdo; /** * @var array Database options. */ private $dbOptions; /** * Constructor. * * List of available options: * * db_table: The name of the table [required] * * db_id_col: The column where to store the session id [default: sess_id] * * db_data_col: The column where to store the session data [default: sess_data] * * db_time_col: The column where to store the timestamp [default: sess_time] * * @param \PDO $pdo A \PDO instance * @param array $dbOptions An associative array of DB options * * @throws \InvalidArgumentException When "db_table" option is not provided */ public function __construct(\PDO $pdo, array $dbOptions = array()) { if (!array_key_exists('db_table', $dbOptions)) { throw new \InvalidArgumentException('You must provide the "db_table" option for a PdoSessionStorage.'); } if (\PDO::ERRMODE_EXCEPTION !== $pdo->getAttribute(\PDO::ATTR_ERRMODE)) { throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__)); } $this->pdo = $pdo; $this->dbOptions = array_merge(array( 'db_id_col' => 'sess_id', 'db_data_col' => 'sess_data', 'db_time_col' => 'sess_time', ), $dbOptions); } /** * {@inheritDoc} */ public function open($path, $name) { return true; } /** * {@inheritDoc} */ public function close() { return true; } /** * {@inheritDoc} */ public function destroy($id) { // get table/column $dbTable = $this->dbOptions['db_table']; $dbIdCol = $this->dbOptions['db_id_col']; // delete the record associated with this id $sql = "DELETE FROM $dbTable WHERE $dbIdCol = :id"; try { $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->execute(); } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e); } return true; } /** * {@inheritDoc} */ public function gc($lifetime) { // get table/column $dbTable = $this->dbOptions['db_table']; $dbTimeCol = $this->dbOptions['db_time_col']; // delete the session records that have expired $sql = "DELETE FROM $dbTable WHERE $dbTimeCol < :time"; try { $stmt = $this->pdo->prepare($sql); $stmt->bindValue(':time', time() - $lifetime, \PDO::PARAM_INT); $stmt->execute(); } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e); } return true; } /** * {@inheritDoc} */ public function read($id) { // get table/columns $dbTable = $this->dbOptions['db_table']; $dbDataCol = $this->dbOptions['db_data_col']; $dbIdCol = $this->dbOptions['db_id_col']; try { $sql = "SELECT $dbDataCol FROM $dbTable WHERE $dbIdCol = :id"; $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->execute(); // it is recommended to use fetchAll so that PDO can close the DB cursor // we anyway expect either no rows, or one row with one column. fetchColumn, seems to be buggy #4777 $sessionRows = $stmt->fetchAll(\PDO::FETCH_NUM); if (count($sessionRows) == 1) { return base64_decode($sessionRows[0][0]); } // session does not exist, create it $this->createNewSession($id); return ''; } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to read the session data: %s', $e->getMessage()), 0, $e); } } /** * {@inheritDoc} */ public function write($id, $data) { // get table/column $dbTable = $this->dbOptions['db_table']; $dbDataCol = $this->dbOptions['db_data_col']; $dbIdCol = $this->dbOptions['db_id_col']; $dbTimeCol = $this->dbOptions['db_time_col']; //session data can contain non binary safe characters so we need to encode it $encoded = base64_encode($data); try { $driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); if ('mysql' === $driver) { // MySQL would report $stmt->rowCount() = 0 on UPDATE when the data is left unchanged // it could result in calling createNewSession() whereas the session already exists in // the DB which would fail as the id is unique $stmt = $this->pdo->prepare( "INSERT INTO $dbTable ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, :time) " . "ON DUPLICATE KEY UPDATE $dbDataCol = VALUES($dbDataCol), $dbTimeCol = VALUES($dbTimeCol)" ); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $stmt->execute(); } elseif ('oci' === $driver) { $stmt = $this->pdo->prepare("MERGE INTO $dbTable USING DUAL ON($dbIdCol = :id) ". "WHEN NOT MATCHED THEN INSERT ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, sysdate) " . "WHEN MATCHED THEN UPDATE SET $dbDataCol = :data WHERE $dbIdCol = :id"); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $stmt->execute(); } else { $stmt = $this->pdo->prepare("UPDATE $dbTable SET $dbDataCol = :data, $dbTimeCol = :time WHERE $dbIdCol = :id"); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $stmt->execute(); if (!$stmt->rowCount()) { // No session exists in the database to update. This happens when we have called // session_regenerate_id() $this->createNewSession($id, $data); } } } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e); } return true; } /** * Creates a new session with the given $id and $data * * @param string $id * @param string $data * * @return boolean True. */ private function createNewSession($id, $data = '') { // get table/column $dbTable = $this->dbOptions['db_table']; $dbDataCol = $this->dbOptions['db_data_col']; $dbIdCol = $this->dbOptions['db_id_col']; $dbTimeCol = $this->dbOptions['db_time_col']; $sql = "INSERT INTO $dbTable ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, :time)"; //session data can contain non binary safe characters so we need to encode it $encoded = base64_encode($data); $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $stmt->execute(); return true; } /** * Return a PDO instance * * @return \PDO */ protected function getConnection() { return $this->pdo; } } PK]>q=HttpFoundation/Session/Storage/Handler/NullSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * NullSessionHandler. * * Can be used in unit testing or in a situations where persisted sessions are not desired. * * @author Drak * * @api */ class NullSessionHandler implements \SessionHandlerInterface { /** * {@inheritdoc} */ public function open($savePath, $sessionName) { return true; } /** * {@inheritdoc} */ public function close() { return true; } /** * {@inheritdoc} */ public function read($sessionId) { return ''; } /** * {@inheritdoc} */ public function write($sessionId, $data) { return true; } /** * {@inheritdoc} */ public function destroy($sessionId) { return true; } /** * {@inheritdoc} */ public function gc($lifetime) { return true; } } PK]k4{ { BHttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * MemcachedSessionHandler. * * Memcached based session storage handler based on the Memcached class * provided by the PHP memcached extension. * * @see http://php.net/memcached * * @author Drak */ class MemcachedSessionHandler implements \SessionHandlerInterface { /** * @var \Memcached Memcached driver. */ private $memcached; /** * @var integer Time to live in seconds */ private $ttl; /** * @var string Key prefix for shared environments. */ private $prefix; /** * Constructor. * * List of available options: * * prefix: The prefix to use for the memcached keys in order to avoid collision * * expiretime: The time to live in seconds * * @param \Memcached $memcached A \Memcached instance * @param array $options An associative array of Memcached options * * @throws \InvalidArgumentException When unsupported options are passed */ public function __construct(\Memcached $memcached, array $options = array()) { $this->memcached = $memcached; if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) { throw new \InvalidArgumentException(sprintf( 'The following options are not supported "%s"', implode(', ', $diff) )); } $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s'; } /** * {@inheritDoc} */ public function open($savePath, $sessionName) { return true; } /** * {@inheritDoc} */ public function close() { return true; } /** * {@inheritDoc} */ public function read($sessionId) { return $this->memcached->get($this->prefix.$sessionId) ?: ''; } /** * {@inheritDoc} */ public function write($sessionId, $data) { return $this->memcached->set($this->prefix.$sessionId, $data, time() + $this->ttl); } /** * {@inheritDoc} */ public function destroy($sessionId) { return $this->memcached->delete($this->prefix.$sessionId); } /** * {@inheritDoc} */ public function gc($lifetime) { // not required here because memcached will auto expire the records anyhow. return true; } /** * Return a Memcached instance * * @return \Memcached */ protected function getMemcached() { return $this->memcached; } } PK]ڏ۹ AHttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * MemcacheSessionHandler. * * @author Drak */ class MemcacheSessionHandler implements \SessionHandlerInterface { /** * @var \Memcache Memcache driver. */ private $memcache; /** * @var integer Time to live in seconds */ private $ttl; /** * @var string Key prefix for shared environments. */ private $prefix; /** * Constructor. * * List of available options: * * prefix: The prefix to use for the memcache keys in order to avoid collision * * expiretime: The time to live in seconds * * @param \Memcache $memcache A \Memcache instance * @param array $options An associative array of Memcache options * * @throws \InvalidArgumentException When unsupported options are passed */ public function __construct(\Memcache $memcache, array $options = array()) { if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) { throw new \InvalidArgumentException(sprintf( 'The following options are not supported "%s"', implode(', ', $diff) )); } $this->memcache = $memcache; $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s'; } /** * {@inheritDoc} */ public function open($savePath, $sessionName) { return true; } /** * {@inheritDoc} */ public function close() { return $this->memcache->close(); } /** * {@inheritDoc} */ public function read($sessionId) { return $this->memcache->get($this->prefix.$sessionId) ?: ''; } /** * {@inheritDoc} */ public function write($sessionId, $data) { return $this->memcache->set($this->prefix.$sessionId, $data, 0, time() + $this->ttl); } /** * {@inheritDoc} */ public function destroy($sessionId) { return $this->memcache->delete($this->prefix.$sessionId); } /** * {@inheritDoc} */ public function gc($lifetime) { // not required here because memcache will auto expire the records anyhow. return true; } /** * Return a Memcache instance * * @return \Memcache */ protected function getMemcache() { return $this->memcache; } } PK]CHttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * Wraps another SessionHandlerInterface to only write the session when it has been modified. * * @author Adrien Brault */ class WriteCheckSessionHandler implements \SessionHandlerInterface { /** * @var \SessionHandlerInterface */ private $wrappedSessionHandler; /** * @var array sessionId => session */ private $readSessions; public function __construct(\SessionHandlerInterface $wrappedSessionHandler) { $this->wrappedSessionHandler = $wrappedSessionHandler; } /** * {@inheritdoc} */ public function close() { return $this->wrappedSessionHandler->close(); } /** * {@inheritdoc} */ public function destroy($sessionId) { return $this->wrappedSessionHandler->destroy($sessionId); } /** * {@inheritdoc} */ public function gc($maxLifetime) { return $this->wrappedSessionHandler->gc($maxLifetime); } /** * {@inheritdoc} */ public function open($savePath, $sessionId) { return $this->wrappedSessionHandler->open($savePath, $sessionId); } /** * {@inheritdoc} */ public function read($sessionId) { $session = $this->wrappedSessionHandler->read($sessionId); $this->readSessions[$sessionId] = $session; return $session; } /** * {@inheritdoc} */ public function write($sessionId, $sessionData) { if (isset($this->readSessions[$sessionId]) && $sessionData === $this->readSessions[$sessionId]) { return true; } return $this->wrappedSessionHandler->write($sessionId, $sessionData); } } PK]33?HttpFoundation/Session/Storage/Handler/NativeSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * Adds SessionHandler functionality if available. * * @see http://php.net/sessionhandler */ if (version_compare(phpversion(), '5.4.0', '>=')) { class NativeSessionHandler extends \SessionHandler {} } else { class NativeSessionHandler {} } PK]?yy:HttpFoundation/Session/Storage/SessionStorageInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * StorageInterface. * * @author Fabien Potencier * @author Drak * * @api */ interface SessionStorageInterface { /** * Starts the session. * * @throws \RuntimeException If something goes wrong starting the session. * * @return boolean True if started. * * @api */ public function start(); /** * Checks if the session is started. * * @return boolean True if started, false otherwise. */ public function isStarted(); /** * Returns the session ID * * @return string The session ID or empty. * * @api */ public function getId(); /** * Sets the session ID * * @param string $id * * @api */ public function setId($id); /** * Returns the session name * * @return mixed The session name. * * @api */ public function getName(); /** * Sets the session name * * @param string $name * * @api */ public function setName($name); /** * Regenerates id that represents this storage. * * This method must invoke session_regenerate_id($destroy) unless * this interface is used for a storage object designed for unit * or functional testing where a real PHP session would interfere * with testing. * * Note regenerate+destroy should not clear the session data in memory * only delete the session data from persistent storage. * * @param Boolean $destroy Destroy session when regenerating? * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. * * @return Boolean True if session regenerated, false if error * * @throws \RuntimeException If an error occurs while regenerating this storage * * @api */ public function regenerate($destroy = false, $lifetime = null); /** * Force the session to be saved and closed. * * This method must invoke session_write_close() unless this interface is * used for a storage object design for unit or functional testing where * a real PHP session would interfere with testing, in which case it * it should actually persist the session data if required. * * @throws \RuntimeException If the session is saved without being started, or if the session * is already closed. */ public function save(); /** * Clear all session data in memory. */ public function clear(); /** * Gets a SessionBagInterface by name. * * @param string $name * * @return SessionBagInterface * * @throws \InvalidArgumentException If the bag does not exist */ public function getBag($name); /** * Registers a SessionBagInterface for use. * * @param SessionBagInterface $bag */ public function registerBag(SessionBagInterface $bag); /** * @return MetadataBag */ public function getMetadataBag(); } PK]t337HttpFoundation/Session/Storage/NativeSessionStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; /** * This provides a base class for session attribute storage. * * @author Drak */ class NativeSessionStorage implements SessionStorageInterface { /** * Array of SessionBagInterface * * @var SessionBagInterface[] */ protected $bags; /** * @var Boolean */ protected $started = false; /** * @var Boolean */ protected $closed = false; /** * @var AbstractProxy */ protected $saveHandler; /** * @var MetadataBag */ protected $metadataBag; /** * Constructor. * * Depending on how you want the storage driver to behave you probably * want to override this constructor entirely. * * List of options for $options array with their defaults. * @see http://php.net/session.configuration for options * but we omit 'session.' from the beginning of the keys for convenience. * * ("auto_start", is not supported as it tells PHP to start a session before * PHP starts to execute user-land code. Setting during runtime has no effect). * * cache_limiter, "nocache" (use "0" to prevent headers from being sent entirely). * cookie_domain, "" * cookie_httponly, "" * cookie_lifetime, "0" * cookie_path, "/" * cookie_secure, "" * entropy_file, "" * entropy_length, "0" * gc_divisor, "100" * gc_maxlifetime, "1440" * gc_probability, "1" * hash_bits_per_character, "4" * hash_function, "0" * name, "PHPSESSID" * referer_check, "" * serialize_handler, "php" * use_cookies, "1" * use_only_cookies, "1" * use_trans_sid, "0" * upload_progress.enabled, "1" * upload_progress.cleanup, "1" * upload_progress.prefix, "upload_progress_" * upload_progress.name, "PHP_SESSION_UPLOAD_PROGRESS" * upload_progress.freq, "1%" * upload_progress.min-freq, "1" * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset=" * * @param array $options Session configuration options. * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler * @param MetadataBag $metaBag MetadataBag. */ public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) { session_cache_limiter(''); // disable by default because it's managed by HeaderBag (if used) ini_set('session.use_cookies', 1); if (version_compare(phpversion(), '5.4.0', '>=')) { session_register_shutdown(); } else { register_shutdown_function('session_write_close'); } $this->setMetadataBag($metaBag); $this->setOptions($options); $this->setSaveHandler($handler); } /** * Gets the save handler instance. * * @return AbstractProxy */ public function getSaveHandler() { return $this->saveHandler; } /** * {@inheritdoc} */ public function start() { if ($this->started && !$this->closed) { return true; } if (version_compare(phpversion(), '5.4.0', '>=') && \PHP_SESSION_ACTIVE === session_status()) { throw new \RuntimeException('Failed to start the session: already started by PHP.'); } if (version_compare(phpversion(), '5.4.0', '<') && isset($_SESSION) && session_id()) { // not 100% fool-proof, but is the most reliable way to determine if a session is active in PHP 5.3 throw new \RuntimeException('Failed to start the session: already started by PHP ($_SESSION is set).'); } if (ini_get('session.use_cookies') && headers_sent($file, $line)) { throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line)); } // ok to try and start the session if (!session_start()) { throw new \RuntimeException('Failed to start the session'); } $this->loadSession(); if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { // This condition matches only PHP 5.3 with internal save handlers $this->saveHandler->setActive(true); } return true; } /** * {@inheritdoc} */ public function getId() { if (!$this->started && !$this->closed) { return ''; // returning empty is consistent with session_id() behaviour } return $this->saveHandler->getId(); } /** * {@inheritdoc} */ public function setId($id) { $this->saveHandler->setId($id); } /** * {@inheritdoc} */ public function getName() { return $this->saveHandler->getName(); } /** * {@inheritdoc} */ public function setName($name) { $this->saveHandler->setName($name); } /** * {@inheritdoc} */ public function regenerate($destroy = false, $lifetime = null) { if (null !== $lifetime) { ini_set('session.cookie_lifetime', $lifetime); } if ($destroy) { $this->metadataBag->stampNew(); } $ret = session_regenerate_id($destroy); // workaround for https://bugs.php.net/bug.php?id=61470 as suggested by David Grudl if ('files' === $this->getSaveHandler()->getSaveHandlerName()) { session_write_close(); if (isset($_SESSION)) { $backup = $_SESSION; session_start(); $_SESSION = $backup; } else { session_start(); } $this->loadSession(); } return $ret; } /** * {@inheritdoc} */ public function save() { session_write_close(); if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { // This condition matches only PHP 5.3 with internal save handlers $this->saveHandler->setActive(false); } $this->closed = true; $this->started = false; } /** * {@inheritdoc} */ public function clear() { // clear out the bags foreach ($this->bags as $bag) { $bag->clear(); } // clear out the session $_SESSION = array(); // reconnect the bags to the session $this->loadSession(); } /** * {@inheritdoc} */ public function registerBag(SessionBagInterface $bag) { $this->bags[$bag->getName()] = $bag; } /** * {@inheritdoc} */ public function getBag($name) { if (!isset($this->bags[$name])) { throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); } if ($this->saveHandler->isActive() && !$this->started) { $this->loadSession(); } elseif (!$this->started) { $this->start(); } return $this->bags[$name]; } /** * Sets the MetadataBag. * * @param MetadataBag $metaBag */ public function setMetadataBag(MetadataBag $metaBag = null) { if (null === $metaBag) { $metaBag = new MetadataBag(); } $this->metadataBag = $metaBag; } /** * Gets the MetadataBag. * * @return MetadataBag */ public function getMetadataBag() { return $this->metadataBag; } /** * {@inheritdoc} */ public function isStarted() { return $this->started; } /** * Sets session.* ini variables. * * For convenience we omit 'session.' from the beginning of the keys. * Explicitly ignores other ini keys. * * @param array $options Session ini directives array(key => value). * * @see http://php.net/session.configuration */ public function setOptions(array $options) { $validOptions = array_flip(array( 'cache_limiter', 'cookie_domain', 'cookie_httponly', 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'entropy_file', 'entropy_length', 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', 'hash_function', 'name', 'referer_check', 'serialize_handler', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags', )); foreach ($options as $key => $value) { if (isset($validOptions[$key])) { ini_set('session.'.$key, $value); } } } /** * Registers session save handler as a PHP session handler. * * To use internal PHP session save handlers, override this method using ini_set with * session.save_handler and session.save_path e.g. * * ini_set('session.save_handler', 'files'); * ini_set('session.save_path', /tmp'); * * or pass in a NativeSessionHandler instance which configures session.save_handler in the * constructor, for a template see NativeFileSessionHandler or use handlers in * composer package drak/native-session * * @see http://php.net/session-set-save-handler * @see http://php.net/sessionhandlerinterface * @see http://php.net/sessionhandler * @see http://github.com/drak/NativeSession * * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $saveHandler * * @throws \InvalidArgumentException */ public function setSaveHandler($saveHandler = null) { if (!$saveHandler instanceof AbstractProxy && !$saveHandler instanceof NativeSessionHandler && !$saveHandler instanceof \SessionHandlerInterface && null !== $saveHandler) { throw new \InvalidArgumentException('Must be instance of AbstractProxy or NativeSessionHandler; implement \SessionHandlerInterface; or be null.'); } // Wrap $saveHandler in proxy and prevent double wrapping of proxy if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { $saveHandler = new SessionHandlerProxy($saveHandler); } elseif (!$saveHandler instanceof AbstractProxy) { $saveHandler = version_compare(phpversion(), '5.4.0', '>=') ? new SessionHandlerProxy(new \SessionHandler()) : new NativeProxy(); } $this->saveHandler = $saveHandler; if ($this->saveHandler instanceof \SessionHandlerInterface) { if (version_compare(phpversion(), '5.4.0', '>=')) { session_set_save_handler($this->saveHandler, false); } else { session_set_save_handler( array($this->saveHandler, 'open'), array($this->saveHandler, 'close'), array($this->saveHandler, 'read'), array($this->saveHandler, 'write'), array($this->saveHandler, 'destroy'), array($this->saveHandler, 'gc') ); } } } /** * Load the session with attributes. * * After starting the session, PHP retrieves the session from whatever handlers * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()). * PHP takes the return value from the read() handler, unserializes it * and populates $_SESSION with the result automatically. * * @param array|null $session */ protected function loadSession(array &$session = null) { if (null === $session) { $session = &$_SESSION; } $bags = array_merge($this->bags, array($this->metadataBag)); foreach ($bags as $bag) { $key = $bag->getStorageKey(); $session[$key] = isset($session[$key]) ? $session[$key] : array(); $bag->initialize($session[$key]); } $this->started = true; $this->closed = false; } } PK]g_.HttpFoundation/Session/Storage/MetadataBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * Metadata container. * * Adds metadata to the session. * * @author Drak */ class MetadataBag implements SessionBagInterface { const CREATED = 'c'; const UPDATED = 'u'; const LIFETIME = 'l'; /** * @var string */ private $name = '__metadata'; /** * @var string */ private $storageKey; /** * @var array */ protected $meta = array(self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0); /** * Unix timestamp. * * @var integer */ private $lastUsed; /** * @var integer */ private $updateThreshold; /** * Constructor. * * @param string $storageKey The key used to store bag in the session. * @param integer $updateThreshold The time to wait between two UPDATED updates */ public function __construct($storageKey = '_sf2_meta', $updateThreshold = 0) { $this->storageKey = $storageKey; $this->updateThreshold = $updateThreshold; } /** * {@inheritdoc} */ public function initialize(array &$array) { $this->meta = &$array; if (isset($array[self::CREATED])) { $this->lastUsed = $this->meta[self::UPDATED]; $timeStamp = time(); if ($timeStamp - $array[self::UPDATED] >= $this->updateThreshold) { $this->meta[self::UPDATED] = $timeStamp; } } else { $this->stampCreated(); } } /** * Gets the lifetime that the session cookie was set with. * * @return integer */ public function getLifetime() { return $this->meta[self::LIFETIME]; } /** * Stamps a new session's metadata. * * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. */ public function stampNew($lifetime = null) { $this->stampCreated($lifetime); } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * Gets the created timestamp metadata. * * @return integer Unix timestamp */ public function getCreated() { return $this->meta[self::CREATED]; } /** * Gets the last used metadata. * * @return integer Unix timestamp */ public function getLastUsed() { return $this->lastUsed; } /** * {@inheritdoc} */ public function clear() { // nothing to do } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * Sets name. * * @param string $name */ public function setName($name) { $this->name = $name; } private function stampCreated($lifetime = null) { $timeStamp = time(); $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; $this->meta[self::LIFETIME] = (null === $lifetime) ? ini_get('session.cookie_lifetime') : $lifetime; } } PK]ގ!:HttpFoundation/Session/Storage/MockArraySessionStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * MockArraySessionStorage mocks the session for unit tests. * * No PHP session is actually started since a session can be initialized * and shutdown only once per PHP execution cycle. * * When doing functional testing, you should use MockFileSessionStorage instead. * * @author Fabien Potencier * @author Bulat Shakirzyanov * @author Drak */ class MockArraySessionStorage implements SessionStorageInterface { /** * @var string */ protected $id = ''; /** * @var string */ protected $name; /** * @var boolean */ protected $started = false; /** * @var boolean */ protected $closed = false; /** * @var array */ protected $data = array(); /** * @var MetadataBag */ protected $metadataBag; /** * @var array */ protected $bags; /** * Constructor. * * @param string $name Session name * @param MetadataBag $metaBag MetadataBag instance. */ public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null) { $this->name = $name; $this->setMetadataBag($metaBag); } /** * Sets the session data. * * @param array $array */ public function setSessionData(array $array) { $this->data = $array; } /** * {@inheritdoc} */ public function start() { if ($this->started && !$this->closed) { return true; } if (empty($this->id)) { $this->id = $this->generateId(); } $this->loadSession(); return true; } /** * {@inheritdoc} */ public function regenerate($destroy = false, $lifetime = null) { if (!$this->started) { $this->start(); } $this->metadataBag->stampNew($lifetime); $this->id = $this->generateId(); return true; } /** * {@inheritdoc} */ public function getId() { return $this->id; } /** * {@inheritdoc} */ public function setId($id) { if ($this->started) { throw new \LogicException('Cannot set session ID after the session has started.'); } $this->id = $id; } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * {@inheritdoc} */ public function setName($name) { $this->name = $name; } /** * {@inheritdoc} */ public function save() { if (!$this->started || $this->closed) { throw new \RuntimeException("Trying to save a session that was not started yet or was already closed"); } // nothing to do since we don't persist the session data $this->closed = false; $this->started = false; } /** * {@inheritdoc} */ public function clear() { // clear out the bags foreach ($this->bags as $bag) { $bag->clear(); } // clear out the session $this->data = array(); // reconnect the bags to the session $this->loadSession(); } /** * {@inheritdoc} */ public function registerBag(SessionBagInterface $bag) { $this->bags[$bag->getName()] = $bag; } /** * {@inheritdoc} */ public function getBag($name) { if (!isset($this->bags[$name])) { throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); } if (!$this->started) { $this->start(); } return $this->bags[$name]; } /** * {@inheritdoc} */ public function isStarted() { return $this->started; } /** * Sets the MetadataBag. * * @param MetadataBag $bag */ public function setMetadataBag(MetadataBag $bag = null) { if (null === $bag) { $bag = new MetadataBag(); } $this->metadataBag = $bag; } /** * Gets the MetadataBag. * * @return MetadataBag */ public function getMetadataBag() { return $this->metadataBag; } /** * Generates a session ID. * * This doesn't need to be particularly cryptographically secure since this is just * a mock. * * @return string */ protected function generateId() { return hash('sha256', uniqid(mt_rand())); } protected function loadSession() { $bags = array_merge($this->bags, array($this->metadataBag)); foreach ($bags as $bag) { $key = $bag->getStorageKey(); $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array(); $bag->initialize($this->data[$key]); } $this->started = true; $this->closed = false; } } PK]M&zrr.HttpFoundation/Session/SessionBagInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; /** * Session Bag store. * * @author Drak */ interface SessionBagInterface { /** * Gets this bag's name * * @return string */ public function getName(); /** * Initializes the Bag * * @param array $array */ public function initialize(array &$array); /** * Gets the storage key for this bag. * * @return string */ public function getStorageKey(); /** * Clears out data from bag. * * @return mixed Whatever data was contained. */ public function clear(); } PK]@WW3HttpFoundation/Session/Flash/AutoExpireFlashBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Flash; /** * AutoExpireFlashBag flash message container. * * @author Drak */ class AutoExpireFlashBag implements FlashBagInterface { private $name = 'flashes'; /** * Flash messages. * * @var array */ private $flashes = array('display' => array(), 'new' => array()); /** * The storage key for flashes in the session * * @var string */ private $storageKey; /** * Constructor. * * @param string $storageKey The key used to store flashes in the session. */ public function __construct($storageKey = '_sf2_flashes') { $this->storageKey = $storageKey; } /** * {@inheritdoc} */ public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } /** * {@inheritdoc} */ public function initialize(array &$flashes) { $this->flashes = &$flashes; // The logic: messages from the last request will be stored in new, so we move them to previous // This request we will show what is in 'display'. What is placed into 'new' this time round will // be moved to display next time round. $this->flashes['display'] = array_key_exists('new', $this->flashes) ? $this->flashes['new'] : array(); $this->flashes['new'] = array(); } /** * {@inheritdoc} */ public function add($type, $message) { $this->flashes['new'][$type][] = $message; } /** * {@inheritdoc} */ public function peek($type, array $default = array()) { return $this->has($type) ? $this->flashes['display'][$type] : $default; } /** * {@inheritdoc} */ public function peekAll() { return array_key_exists('display', $this->flashes) ? (array) $this->flashes['display'] : array(); } /** * {@inheritdoc} */ public function get($type, array $default = array()) { $return = $default; if (!$this->has($type)) { return $return; } if (isset($this->flashes['display'][$type])) { $return = $this->flashes['display'][$type]; unset($this->flashes['display'][$type]); } return $return; } /** * {@inheritdoc} */ public function all() { $return = $this->flashes['display']; $this->flashes = array('new' => array(), 'display' => array()); return $return; } /** * {@inheritdoc} */ public function setAll(array $messages) { $this->flashes['new'] = $messages; } /** * {@inheritdoc} */ public function set($type, $messages) { $this->flashes['new'][$type] = (array) $messages; } /** * {@inheritdoc} */ public function has($type) { return array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; } /** * {@inheritdoc} */ public function keys() { return array_keys($this->flashes['display']); } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * {@inheritdoc} */ public function clear() { return $this->all(); } } PK]a2HttpFoundation/Session/Flash/FlashBagInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Flash; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * FlashBagInterface. * * @author Drak */ interface FlashBagInterface extends SessionBagInterface { /** * Adds a flash message for type. * * @param string $type * @param string $message */ public function add($type, $message); /** * Registers a message for a given type. * * @param string $type * @param string|array $message */ public function set($type, $message); /** * Gets flash messages for a given type. * * @param string $type Message category type. * @param array $default Default value if $type does not exist. * * @return array */ public function peek($type, array $default = array()); /** * Gets all flash messages. * * @return array */ public function peekAll(); /** * Gets and clears flash from the stack. * * @param string $type * @param array $default Default value if $type does not exist. * * @return array */ public function get($type, array $default = array()); /** * Gets and clears flashes from the stack. * * @return array */ public function all(); /** * Sets all flash messages. */ public function setAll(array $messages); /** * Has flash messages for a given type? * * @param string $type * * @return boolean */ public function has($type); /** * Returns a list of all defined types. * * @return array */ public function keys(); } PK]W )HttpFoundation/Session/Flash/FlashBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Flash; /** * FlashBag flash message container. * * \IteratorAggregate implementation is deprecated and will be removed in 3.0. * * @author Drak */ class FlashBag implements FlashBagInterface, \IteratorAggregate { private $name = 'flashes'; /** * Flash messages. * * @var array */ private $flashes = array(); /** * The storage key for flashes in the session * * @var string */ private $storageKey; /** * Constructor. * * @param string $storageKey The key used to store flashes in the session. */ public function __construct($storageKey = '_sf2_flashes') { $this->storageKey = $storageKey; } /** * {@inheritdoc} */ public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } /** * {@inheritdoc} */ public function initialize(array &$flashes) { $this->flashes = &$flashes; } /** * {@inheritdoc} */ public function add($type, $message) { $this->flashes[$type][] = $message; } /** * {@inheritdoc} */ public function peek($type, array $default = array()) { return $this->has($type) ? $this->flashes[$type] : $default; } /** * {@inheritdoc} */ public function peekAll() { return $this->flashes; } /** * {@inheritdoc} */ public function get($type, array $default = array()) { if (!$this->has($type)) { return $default; } $return = $this->flashes[$type]; unset($this->flashes[$type]); return $return; } /** * {@inheritdoc} */ public function all() { $return = $this->peekAll(); $this->flashes = array(); return $return; } /** * {@inheritdoc} */ public function set($type, $messages) { $this->flashes[$type] = (array) $messages; } /** * {@inheritdoc} */ public function setAll(array $messages) { $this->flashes = $messages; } /** * {@inheritdoc} */ public function has($type) { return array_key_exists($type, $this->flashes) && $this->flashes[$type]; } /** * {@inheritdoc} */ public function keys() { return array_keys($this->flashes); } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * {@inheritdoc} */ public function clear() { return $this->all(); } /** * Returns an iterator for flashes. * * @deprecated Will be removed in 3.0. * * @return \ArrayIterator An \ArrayIterator instance */ public function getIterator() { return new \ArrayIterator($this->all()); } } PK]:au77"HttpFoundation/Session/Session.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; /** * Session. * * @author Fabien Potencier * @author Drak * * @api */ class Session implements SessionInterface, \IteratorAggregate, \Countable { /** * Storage driver. * * @var SessionStorageInterface */ protected $storage; /** * @var string */ private $flashName; /** * @var string */ private $attributeName; /** * Constructor. * * @param SessionStorageInterface $storage A SessionStorageInterface instance. * @param AttributeBagInterface $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag) * @param FlashBagInterface $flashes A FlashBagInterface instance (defaults null for default FlashBag) */ public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null) { $this->storage = $storage ?: new NativeSessionStorage(); $attributes = $attributes ?: new AttributeBag(); $this->attributeName = $attributes->getName(); $this->registerBag($attributes); $flashes = $flashes ?: new FlashBag(); $this->flashName = $flashes->getName(); $this->registerBag($flashes); } /** * {@inheritdoc} */ public function start() { return $this->storage->start(); } /** * {@inheritdoc} */ public function has($name) { return $this->storage->getBag($this->attributeName)->has($name); } /** * {@inheritdoc} */ public function get($name, $default = null) { return $this->storage->getBag($this->attributeName)->get($name, $default); } /** * {@inheritdoc} */ public function set($name, $value) { $this->storage->getBag($this->attributeName)->set($name, $value); } /** * {@inheritdoc} */ public function all() { return $this->storage->getBag($this->attributeName)->all(); } /** * {@inheritdoc} */ public function replace(array $attributes) { $this->storage->getBag($this->attributeName)->replace($attributes); } /** * {@inheritdoc} */ public function remove($name) { return $this->storage->getBag($this->attributeName)->remove($name); } /** * {@inheritdoc} */ public function clear() { $this->storage->getBag($this->attributeName)->clear(); } /** * {@inheritdoc} */ public function isStarted() { return $this->storage->isStarted(); } /** * Returns an iterator for attributes. * * @return \ArrayIterator An \ArrayIterator instance */ public function getIterator() { return new \ArrayIterator($this->storage->getBag($this->attributeName)->all()); } /** * Returns the number of attributes. * * @return int The number of attributes */ public function count() { return count($this->storage->getBag($this->attributeName)->all()); } /** * {@inheritdoc} */ public function invalidate($lifetime = null) { $this->storage->clear(); return $this->migrate(true, $lifetime); } /** * {@inheritdoc} */ public function migrate($destroy = false, $lifetime = null) { return $this->storage->regenerate($destroy, $lifetime); } /** * {@inheritdoc} */ public function save() { $this->storage->save(); } /** * {@inheritdoc} */ public function getId() { return $this->storage->getId(); } /** * {@inheritdoc} */ public function setId($id) { $this->storage->setId($id); } /** * {@inheritdoc} */ public function getName() { return $this->storage->getName(); } /** * {@inheritdoc} */ public function setName($name) { $this->storage->setName($name); } /** * {@inheritdoc} */ public function getMetadataBag() { return $this->storage->getMetadataBag(); } /** * {@inheritdoc} */ public function registerBag(SessionBagInterface $bag) { $this->storage->registerBag($bag); } /** * {@inheritdoc} */ public function getBag($name) { return $this->storage->getBag($name); } /** * Gets the flashbag interface. * * @return FlashBagInterface */ public function getFlashBag() { return $this->getBag($this->flashName); } } PK]0H66;HttpFoundation/Session/Attribute/NamespacedAttributeBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Attribute; /** * This class provides structured storage of session attributes using * a name spacing character in the key. * * @author Drak */ class NamespacedAttributeBag extends AttributeBag { /** * Namespace character. * * @var string */ private $namespaceCharacter; /** * Constructor. * * @param string $storageKey Session storage key. * @param string $namespaceCharacter Namespace character to use in keys. */ public function __construct($storageKey = '_sf2_attributes', $namespaceCharacter = '/') { $this->namespaceCharacter = $namespaceCharacter; parent::__construct($storageKey); } /** * {@inheritdoc} */ public function has($name) { $attributes = $this->resolveAttributePath($name); $name = $this->resolveKey($name); if (null === $attributes) { return false; } return array_key_exists($name, $attributes); } /** * {@inheritdoc} */ public function get($name, $default = null) { $attributes = $this->resolveAttributePath($name); $name = $this->resolveKey($name); if (null === $attributes) { return $default; } return array_key_exists($name, $attributes) ? $attributes[$name] : $default; } /** * {@inheritdoc} */ public function set($name, $value) { $attributes = & $this->resolveAttributePath($name, true); $name = $this->resolveKey($name); $attributes[$name] = $value; } /** * {@inheritdoc} */ public function remove($name) { $retval = null; $attributes = & $this->resolveAttributePath($name); $name = $this->resolveKey($name); if (null !== $attributes && array_key_exists($name, $attributes)) { $retval = $attributes[$name]; unset($attributes[$name]); } return $retval; } /** * Resolves a path in attributes property and returns it as a reference. * * This method allows structured namespacing of session attributes. * * @param string $name Key name * @param boolean $writeContext Write context, default false * * @return array */ protected function &resolveAttributePath($name, $writeContext = false) { $array = & $this->attributes; $name = (strpos($name, $this->namespaceCharacter) === 0) ? substr($name, 1) : $name; // Check if there is anything to do, else return if (!$name) { return $array; } $parts = explode($this->namespaceCharacter, $name); if (count($parts) < 2) { if (!$writeContext) { return $array; } $array[$parts[0]] = array(); return $array; } unset($parts[count($parts)-1]); foreach ($parts as $part) { if (null !== $array && !array_key_exists($part, $array)) { $array[$part] = $writeContext ? array() : null; } $array = & $array[$part]; } return $array; } /** * Resolves the key from the name. * * This is the last part in a dot separated string. * * @param string $name * * @return string */ protected function resolveKey($name) { if (false !== $pos = strrpos($name, $this->namespaceCharacter)) { $name = substr($name, $pos+1); } return $name; } } PK]e  :HttpFoundation/Session/Attribute/AttributeBagInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Attribute; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * Attributes store. * * @author Drak */ interface AttributeBagInterface extends SessionBagInterface { /** * Checks if an attribute is defined. * * @param string $name The attribute name * * @return Boolean true if the attribute is defined, false otherwise */ public function has($name); /** * Returns an attribute. * * @param string $name The attribute name * @param mixed $default The default value if not found * * @return mixed */ public function get($name, $default = null); /** * Sets an attribute. * * @param string $name * @param mixed $value */ public function set($name, $value); /** * Returns attributes. * * @return array Attributes */ public function all(); /** * Sets attributes. * * @param array $attributes Attributes */ public function replace(array $attributes); /** * Removes an attribute. * * @param string $name * * @return mixed The removed value or null when it does not exist */ public function remove($name); } PK]( 1HttpFoundation/Session/Attribute/AttributeBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Attribute; /** * This class relates to session attribute storage */ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable { private $name = 'attributes'; /** * @var string */ private $storageKey; /** * @var array */ protected $attributes = array(); /** * Constructor. * * @param string $storageKey The key used to store attributes in the session */ public function __construct($storageKey = '_sf2_attributes') { $this->storageKey = $storageKey; } /** * {@inheritdoc} */ public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } /** * {@inheritdoc} */ public function initialize(array &$attributes) { $this->attributes = &$attributes; } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * {@inheritdoc} */ public function has($name) { return array_key_exists($name, $this->attributes); } /** * {@inheritdoc} */ public function get($name, $default = null) { return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** * {@inheritdoc} */ public function set($name, $value) { $this->attributes[$name] = $value; } /** * {@inheritdoc} */ public function all() { return $this->attributes; } /** * {@inheritdoc} */ public function replace(array $attributes) { $this->attributes = array(); foreach ($attributes as $key => $value) { $this->set($key, $value); } } /** * {@inheritdoc} */ public function remove($name) { $retval = null; if (array_key_exists($name, $this->attributes)) { $retval = $this->attributes[$name]; unset($this->attributes[$name]); } return $retval; } /** * {@inheritdoc} */ public function clear() { $return = $this->attributes; $this->attributes = array(); return $return; } /** * Returns an iterator for attributes. * * @return \ArrayIterator An \ArrayIterator instance */ public function getIterator() { return new \ArrayIterator($this->attributes); } /** * Returns the number of attributes. * * @return integer The number of attributes */ public function count() { return count($this->attributes); } } PK]=\\+HttpFoundation/Session/SessionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; /** * Interface for the session. * * @author Drak */ interface SessionInterface { /** * Starts the session storage. * * @return Boolean True if session started. * * @throws \RuntimeException If session fails to start. * * @api */ public function start(); /** * Returns the session ID. * * @return string The session ID. * * @api */ public function getId(); /** * Sets the session ID * * @param string $id * * @api */ public function setId($id); /** * Returns the session name. * * @return mixed The session name. * * @api */ public function getName(); /** * Sets the session name. * * @param string $name * * @api */ public function setName($name); /** * Invalidates the current session. * * Clears all session attributes and flashes and regenerates the * session and deletes the old session from persistence. * * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. * * @return Boolean True if session invalidated, false if error. * * @api */ public function invalidate($lifetime = null); /** * Migrates the current session to a new session id while maintaining all * session attributes. * * @param Boolean $destroy Whether to delete the old session or leave it to garbage collection. * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. * * @return Boolean True if session migrated, false if error. * * @api */ public function migrate($destroy = false, $lifetime = null); /** * Force the session to be saved and closed. * * This method is generally not required for real sessions as * the session will be automatically saved at the end of * code execution. */ public function save(); /** * Checks if an attribute is defined. * * @param string $name The attribute name * * @return Boolean true if the attribute is defined, false otherwise * * @api */ public function has($name); /** * Returns an attribute. * * @param string $name The attribute name * @param mixed $default The default value if not found. * * @return mixed * * @api */ public function get($name, $default = null); /** * Sets an attribute. * * @param string $name * @param mixed $value * * @api */ public function set($name, $value); /** * Returns attributes. * * @return array Attributes * * @api */ public function all(); /** * Sets attributes. * * @param array $attributes Attributes */ public function replace(array $attributes); /** * Removes an attribute. * * @param string $name * * @return mixed The removed value or null when it does not exist * * @api */ public function remove($name); /** * Clears all attributes. * * @api */ public function clear(); /** * Checks if the session was started. * * @return Boolean */ public function isStarted(); /** * Registers a SessionBagInterface with the session. * * @param SessionBagInterface $bag */ public function registerBag(SessionBagInterface $bag); /** * Gets a bag instance by name. * * @param string $name * * @return SessionBagInterface */ public function getBag($name); /** * Gets session meta. * * @return MetadataBag */ public function getMetadataBag(); } PK]K> HttpFoundation/ApacheRequest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Request represents an HTTP request from an Apache server. * * @author Fabien Potencier */ class ApacheRequest extends Request { /** * {@inheritdoc} */ protected function prepareRequestUri() { return $this->server->get('REQUEST_URI'); } /** * {@inheritdoc} */ protected function prepareBaseUrl() { $baseUrl = $this->server->get('SCRIPT_NAME'); if (false === strpos($this->server->get('REQUEST_URI'), $baseUrl)) { // assume mod_rewrite return rtrim(dirname($baseUrl), '/\\'); } return $baseUrl; } } PK]qugddHttpFoundation/Request.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\Session\SessionInterface; /** * Request represents an HTTP request. * * The methods dealing with URL accept / return a raw path (% encoded): * * getBasePath * * getBaseUrl * * getPathInfo * * getRequestUri * * getUri * * getUriForPath * * @author Fabien Potencier * * @api */ class Request { const HEADER_CLIENT_IP = 'client_ip'; const HEADER_CLIENT_HOST = 'client_host'; const HEADER_CLIENT_PROTO = 'client_proto'; const HEADER_CLIENT_PORT = 'client_port'; protected static $trustedProxies = array(); /** * @var string[] */ protected static $trustedHostPatterns = array(); /** * @var string[] */ protected static $trustedHosts = array(); /** * Names for headers that can be trusted when * using trusted proxies. * * The default names are non-standard, but widely used * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). */ protected static $trustedHeaders = array( self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', ); protected static $httpMethodParameterOverride = false; /** * Custom parameters * * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $attributes; /** * Request body parameters ($_POST) * * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $request; /** * Query string parameters ($_GET) * * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $query; /** * Server and execution environment parameters ($_SERVER) * * @var \Symfony\Component\HttpFoundation\ServerBag * * @api */ public $server; /** * Uploaded files ($_FILES) * * @var \Symfony\Component\HttpFoundation\FileBag * * @api */ public $files; /** * Cookies ($_COOKIE) * * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $cookies; /** * Headers (taken from the $_SERVER) * * @var \Symfony\Component\HttpFoundation\HeaderBag * * @api */ public $headers; /** * @var string */ protected $content; /** * @var array */ protected $languages; /** * @var array */ protected $charsets; /** * @var array */ protected $encodings; /** * @var array */ protected $acceptableContentTypes; /** * @var string */ protected $pathInfo; /** * @var string */ protected $requestUri; /** * @var string */ protected $baseUrl; /** * @var string */ protected $basePath; /** * @var string */ protected $method; /** * @var string */ protected $format; /** * @var \Symfony\Component\HttpFoundation\Session\SessionInterface */ protected $session; /** * @var string */ protected $locale; /** * @var string */ protected $defaultLocale = 'en'; /** * @var array */ protected static $formats; protected static $requestFactory; /** * Constructor. * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * @param string $content The raw body data * * @api */ public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); } /** * Sets the parameters for this request. * * This method also re-initializes all properties. * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * @param string $content The raw body data * * @api */ public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { $this->request = new ParameterBag($request); $this->query = new ParameterBag($query); $this->attributes = new ParameterBag($attributes); $this->cookies = new ParameterBag($cookies); $this->files = new FileBag($files); $this->server = new ServerBag($server); $this->headers = new HeaderBag($this->server->getHeaders()); $this->content = $content; $this->languages = null; $this->charsets = null; $this->encodings = null; $this->acceptableContentTypes = null; $this->pathInfo = null; $this->requestUri = null; $this->baseUrl = null; $this->basePath = null; $this->method = null; $this->format = null; } /** * Creates a new request with values from PHP's super globals. * * @return Request A new request * * @api */ public static function createFromGlobals() { $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER); if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded') && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH')) ) { parse_str($request->getContent(), $data); $request->request = new ParameterBag($data); } return $request; } /** * Creates a Request based on a given URI and configuration. * * The information contained in the URI always take precedence * over the other information (server and parameters). * * @param string $uri The URI * @param string $method The HTTP method * @param array $parameters The query (GET) or request (POST) parameters * @param array $cookies The request cookies ($_COOKIE) * @param array $files The request files ($_FILES) * @param array $server The server parameters ($_SERVER) * @param string $content The raw body data * * @return Request A Request instance * * @api */ public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null) { $server = array_replace(array( 'SERVER_NAME' => 'localhost', 'SERVER_PORT' => 80, 'HTTP_HOST' => 'localhost', 'HTTP_USER_AGENT' => 'Symfony/2.X', 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'REMOTE_ADDR' => '127.0.0.1', 'SCRIPT_NAME' => '', 'SCRIPT_FILENAME' => '', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_TIME' => time(), ), $server); $server['PATH_INFO'] = ''; $server['REQUEST_METHOD'] = strtoupper($method); $components = parse_url($uri); if (isset($components['host'])) { $server['SERVER_NAME'] = $components['host']; $server['HTTP_HOST'] = $components['host']; } if (isset($components['scheme'])) { if ('https' === $components['scheme']) { $server['HTTPS'] = 'on'; $server['SERVER_PORT'] = 443; } else { unset($server['HTTPS']); $server['SERVER_PORT'] = 80; } } if (isset($components['port'])) { $server['SERVER_PORT'] = $components['port']; $server['HTTP_HOST'] = $server['HTTP_HOST'].':'.$components['port']; } if (isset($components['user'])) { $server['PHP_AUTH_USER'] = $components['user']; } if (isset($components['pass'])) { $server['PHP_AUTH_PW'] = $components['pass']; } if (!isset($components['path'])) { $components['path'] = '/'; } switch (strtoupper($method)) { case 'POST': case 'PUT': case 'DELETE': if (!isset($server['CONTENT_TYPE'])) { $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; } case 'PATCH': $request = $parameters; $query = array(); break; default: $request = array(); $query = $parameters; break; } $queryString = ''; if (isset($components['query'])) { parse_str(html_entity_decode($components['query']), $qs); if ($query) { $query = array_replace($qs, $query); $queryString = http_build_query($query, '', '&'); } else { $query = $qs; $queryString = $components['query']; } } elseif ($query) { $queryString = http_build_query($query, '', '&'); } $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : ''); $server['QUERY_STRING'] = $queryString; return self::createRequestFromFactory($query, $request, array(), $cookies, $files, $server, $content); } /** * Sets a callable able to create a Request instance. * * This is mainly useful when you need to override the Request class * to keep BC with an existing system. It should not be used for any * other purpose. * * @param callable|null $callable A PHP callable */ public static function setFactory($callable) { self::$requestFactory = $callable; } /** * Clones a request and overrides some of its parameters. * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * * @return Request The duplicated request * * @api */ public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) { $dup = clone $this; if ($query !== null) { $dup->query = new ParameterBag($query); } if ($request !== null) { $dup->request = new ParameterBag($request); } if ($attributes !== null) { $dup->attributes = new ParameterBag($attributes); } if ($cookies !== null) { $dup->cookies = new ParameterBag($cookies); } if ($files !== null) { $dup->files = new FileBag($files); } if ($server !== null) { $dup->server = new ServerBag($server); $dup->headers = new HeaderBag($dup->server->getHeaders()); } $dup->languages = null; $dup->charsets = null; $dup->encodings = null; $dup->acceptableContentTypes = null; $dup->pathInfo = null; $dup->requestUri = null; $dup->baseUrl = null; $dup->basePath = null; $dup->method = null; $dup->format = null; if (!$dup->get('_format') && $this->get('_format')) { $dup->attributes->set('_format', $this->get('_format')); } if (!$dup->getRequestFormat(null)) { $dup->setRequestFormat($format = $this->getRequestFormat(null)); } return $dup; } /** * Clones the current request. * * Note that the session is not cloned as duplicated requests * are most of the time sub-requests of the main one. */ public function __clone() { $this->query = clone $this->query; $this->request = clone $this->request; $this->attributes = clone $this->attributes; $this->cookies = clone $this->cookies; $this->files = clone $this->files; $this->server = clone $this->server; $this->headers = clone $this->headers; } /** * Returns the request as a string. * * @return string The request */ public function __toString() { return sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n". $this->headers."\r\n". $this->getContent(); } /** * Overrides the PHP global variables according to this request instance. * * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. * $_FILES is never override, see rfc1867 * * @api */ public function overrideGlobals() { $_GET = $this->query->all(); $_POST = $this->request->all(); $_SERVER = $this->server->all(); $_COOKIE = $this->cookies->all(); foreach ($this->headers->all() as $key => $value) { $key = strtoupper(str_replace('-', '_', $key)); if (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH'))) { $_SERVER[$key] = implode(', ', $value); } else { $_SERVER['HTTP_'.$key] = implode(', ', $value); } } $request = array('g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE); $requestOrder = ini_get('request_order') ?: ini_get('variables_order'); $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; $_REQUEST = array(); foreach (str_split($requestOrder) as $order) { $_REQUEST = array_merge($_REQUEST, $request[$order]); } } /** * Sets a list of trusted proxies. * * You should only list the reverse proxies that you manage directly. * * @param array $proxies A list of trusted proxies * * @api */ public static function setTrustedProxies(array $proxies) { self::$trustedProxies = $proxies; } /** * Gets the list of trusted proxies. * * @return array An array of trusted proxies. */ public static function getTrustedProxies() { return self::$trustedProxies; } /** * Sets a list of trusted host patterns. * * You should only list the hosts you manage using regexs. * * @param array $hostPatterns A list of trusted host patterns */ public static function setTrustedHosts(array $hostPatterns) { self::$trustedHostPatterns = array_map(function ($hostPattern) { return sprintf('{%s}i', str_replace('}', '\\}', $hostPattern)); }, $hostPatterns); // we need to reset trusted hosts on trusted host patterns change self::$trustedHosts = array(); } /** * Gets the list of trusted host patterns. * * @return array An array of trusted host patterns. */ public static function getTrustedHosts() { return self::$trustedHostPatterns; } /** * Sets the name for trusted headers. * * The following header keys are supported: * * * Request::HEADER_CLIENT_IP: defaults to X-Forwarded-For (see getClientIp()) * * Request::HEADER_CLIENT_HOST: defaults to X-Forwarded-Host (see getClientHost()) * * Request::HEADER_CLIENT_PORT: defaults to X-Forwarded-Port (see getClientPort()) * * Request::HEADER_CLIENT_PROTO: defaults to X-Forwarded-Proto (see getScheme() and isSecure()) * * Setting an empty value allows to disable the trusted header for the given key. * * @param string $key The header key * @param string $value The header name * * @throws \InvalidArgumentException */ public static function setTrustedHeaderName($key, $value) { if (!array_key_exists($key, self::$trustedHeaders)) { throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key)); } self::$trustedHeaders[$key] = $value; } /** * Gets the trusted proxy header name. * * @param string $key The header key * * @return string The header name * * @throws \InvalidArgumentException */ public static function getTrustedHeaderName($key) { if (!array_key_exists($key, self::$trustedHeaders)) { throw new \InvalidArgumentException(sprintf('Unable to get the trusted header name for key "%s".', $key)); } return self::$trustedHeaders[$key]; } /** * Normalizes a query string. * * It builds a normalized query string, where keys/value pairs are alphabetized, * have consistent escaping and unneeded delimiters are removed. * * @param string $qs Query string * * @return string A normalized query string for the Request */ public static function normalizeQueryString($qs) { if ('' == $qs) { return ''; } $parts = array(); $order = array(); foreach (explode('&', $qs) as $param) { if ('' === $param || '=' === $param[0]) { // Ignore useless delimiters, e.g. "x=y&". // Also ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway. // PHP also does not include them when building _GET. continue; } $keyValuePair = explode('=', $param, 2); // GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded). // PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str. This is why we use urldecode and then normalize to // RFC 3986 with rawurlencode. $parts[] = isset($keyValuePair[1]) ? rawurlencode(urldecode($keyValuePair[0])).'='.rawurlencode(urldecode($keyValuePair[1])) : rawurlencode(urldecode($keyValuePair[0])); $order[] = urldecode($keyValuePair[0]); } array_multisort($order, SORT_ASC, $parts); return implode('&', $parts); } /** * Enables support for the _method request parameter to determine the intended HTTP method. * * Be warned that enabling this feature might lead to CSRF issues in your code. * Check that you are using CSRF tokens when required. * * The HTTP method can only be overridden when the real HTTP method is POST. */ public static function enableHttpMethodParameterOverride() { self::$httpMethodParameterOverride = true; } /** * Checks whether support for the _method request parameter is enabled. * * @return Boolean True when the _method request parameter is enabled, false otherwise */ public static function getHttpMethodParameterOverride() { return self::$httpMethodParameterOverride; } /** * Gets a "parameter" value. * * This method is mainly useful for libraries that want to provide some flexibility. * * Order of precedence: GET, PATH, POST * * Avoid using this method in controllers: * * * slow * * prefer to get from a "named" source * * It is better to explicitly get request parameters from the appropriate * public property instead (query, attributes, request). * * @param string $key the key * @param mixed $default the default value * @param Boolean $deep is parameter deep in multidimensional array * * @return mixed */ public function get($key, $default = null, $deep = false) { return $this->query->get($key, $this->attributes->get($key, $this->request->get($key, $default, $deep), $deep), $deep); } /** * Gets the Session. * * @return SessionInterface|null The session * * @api */ public function getSession() { return $this->session; } /** * Whether the request contains a Session which was started in one of the * previous requests. * * @return Boolean * * @api */ public function hasPreviousSession() { // the check for $this->session avoids malicious users trying to fake a session cookie with proper name return $this->hasSession() && $this->cookies->has($this->session->getName()); } /** * Whether the request contains a Session object. * * This method does not give any information about the state of the session object, * like whether the session is started or not. It is just a way to check if this Request * is associated with a Session instance. * * @return Boolean true when the Request contains a Session object, false otherwise * * @api */ public function hasSession() { return null !== $this->session; } /** * Sets the Session. * * @param SessionInterface $session The Session * * @api */ public function setSession(SessionInterface $session) { $this->session = $session; } /** * Returns the client IP addresses. * * In the returned array the most trusted IP address is first, and the * least trusted one last. The "real" client IP address is the last one, * but this is also the least trusted one. Trusted proxies are stripped. * * Use this method carefully; you should use getClientIp() instead. * * @return array The client IP addresses * * @see getClientIp() */ public function getClientIps() { $ip = $this->server->get('REMOTE_ADDR'); if (!self::$trustedProxies) { return array($ip); } if (!self::$trustedHeaders[self::HEADER_CLIENT_IP] || !$this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) { return array($ip); } $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP]))); $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from $ip = $clientIps[0]; // Fallback to this when the client IP falls into the range of trusted proxies // Eliminate all IPs from the forwarded IP chain which are trusted proxies foreach ($clientIps as $key => $clientIp) { if (IpUtils::checkIp($clientIp, self::$trustedProxies)) { unset($clientIps[$key]); } } // Now the IP chain contains only untrusted proxies and the client IP return $clientIps ? array_reverse($clientIps) : array($ip); } /** * Returns the client IP address. * * This method can read the client IP address from the "X-Forwarded-For" header * when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For" * header value is a comma+space separated list of IP addresses, the left-most * being the original client, and each successive proxy that passed the request * adding the IP address where it received the request from. * * If your reverse proxy uses a different header name than "X-Forwarded-For", * ("Client-Ip" for instance), configure it via "setTrustedHeaderName()" with * the "client-ip" key. * * @return string The client IP address * * @see getClientIps() * @see http://en.wikipedia.org/wiki/X-Forwarded-For * * @api */ public function getClientIp() { $ipAddresses = $this->getClientIps(); return $ipAddresses[0]; } /** * Returns current script name. * * @return string * * @api */ public function getScriptName() { return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', '')); } /** * Returns the path being requested relative to the executed script. * * The path info always starts with a /. * * Suppose this request is instantiated from /mysite on localhost: * * * http://localhost/mysite returns an empty string * * http://localhost/mysite/about returns '/about' * * http://localhost/mysite/enco%20ded returns '/enco%20ded' * * http://localhost/mysite/about?var=1 returns '/about' * * @return string The raw path (i.e. not urldecoded) * * @api */ public function getPathInfo() { if (null === $this->pathInfo) { $this->pathInfo = $this->preparePathInfo(); } return $this->pathInfo; } /** * Returns the root path from which this request is executed. * * Suppose that an index.php file instantiates this request object: * * * http://localhost/index.php returns an empty string * * http://localhost/index.php/page returns an empty string * * http://localhost/web/index.php returns '/web' * * http://localhost/we%20b/index.php returns '/we%20b' * * @return string The raw path (i.e. not urldecoded) * * @api */ public function getBasePath() { if (null === $this->basePath) { $this->basePath = $this->prepareBasePath(); } return $this->basePath; } /** * Returns the root URL from which this request is executed. * * The base URL never ends with a /. * * This is similar to getBasePath(), except that it also includes the * script filename (e.g. index.php) if one exists. * * @return string The raw URL (i.e. not urldecoded) * * @api */ public function getBaseUrl() { if (null === $this->baseUrl) { $this->baseUrl = $this->prepareBaseUrl(); } return $this->baseUrl; } /** * Gets the request's scheme. * * @return string * * @api */ public function getScheme() { return $this->isSecure() ? 'https' : 'http'; } /** * Returns the port on which the request is made. * * This method can read the client port from the "X-Forwarded-Port" header * when trusted proxies were set via "setTrustedProxies()". * * The "X-Forwarded-Port" header must contain the client port. * * If your reverse proxy uses a different header name than "X-Forwarded-Port", * configure it via "setTrustedHeaderName()" with the "client-port" key. * * @return string * * @api */ public function getPort() { if (self::$trustedProxies) { if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && $port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT])) { return $port; } if (self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && 'https' === $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO], 'http')) { return 443; } } if ($host = $this->headers->get('HOST')) { if (false !== $pos = strrpos($host, ':')) { return intval(substr($host, $pos + 1)); } return 'https' === $this->getScheme() ? 443 : 80; } return $this->server->get('SERVER_PORT'); } /** * Returns the user. * * @return string|null */ public function getUser() { return $this->server->get('PHP_AUTH_USER'); } /** * Returns the password. * * @return string|null */ public function getPassword() { return $this->server->get('PHP_AUTH_PW'); } /** * Gets the user info. * * @return string A user name and, optionally, scheme-specific information about how to gain authorization to access the server */ public function getUserInfo() { $userinfo = $this->getUser(); $pass = $this->getPassword(); if ('' != $pass) { $userinfo .= ":$pass"; } return $userinfo; } /** * Returns the HTTP host being requested. * * The port name will be appended to the host if it's non-standard. * * @return string * * @api */ public function getHttpHost() { $scheme = $this->getScheme(); $port = $this->getPort(); if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) { return $this->getHost(); } return $this->getHost().':'.$port; } /** * Returns the requested URI. * * @return string The raw URI (i.e. not urldecoded) * * @api */ public function getRequestUri() { if (null === $this->requestUri) { $this->requestUri = $this->prepareRequestUri(); } return $this->requestUri; } /** * Gets the scheme and HTTP host. * * If the URL was called with basic authentication, the user * and the password are not added to the generated string. * * @return string The scheme and HTTP host */ public function getSchemeAndHttpHost() { return $this->getScheme().'://'.$this->getHttpHost(); } /** * Generates a normalized URI for the Request. * * @return string A normalized URI for the Request * * @see getQueryString() * * @api */ public function getUri() { if (null !== $qs = $this->getQueryString()) { $qs = '?'.$qs; } return $this->getSchemeAndHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs; } /** * Generates a normalized URI for the given path. * * @param string $path A path to use instead of the current one * * @return string The normalized URI for the path * * @api */ public function getUriForPath($path) { return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path; } /** * Generates the normalized query string for the Request. * * It builds a normalized query string, where keys/value pairs are alphabetized * and have consistent escaping. * * @return string|null A normalized query string for the Request * * @api */ public function getQueryString() { $qs = static::normalizeQueryString($this->server->get('QUERY_STRING')); return '' === $qs ? null : $qs; } /** * Checks whether the request is secure or not. * * This method can read the client port from the "X-Forwarded-Proto" header * when trusted proxies were set via "setTrustedProxies()". * * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". * * If your reverse proxy uses a different header name than "X-Forwarded-Proto" * ("SSL_HTTPS" for instance), configure it via "setTrustedHeaderName()" with * the "client-proto" key. * * @return Boolean * * @api */ public function isSecure() { if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) { return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1')); } return 'on' == strtolower($this->server->get('HTTPS')) || 1 == $this->server->get('HTTPS'); } /** * Returns the host name. * * This method can read the client port from the "X-Forwarded-Host" header * when trusted proxies were set via "setTrustedProxies()". * * The "X-Forwarded-Host" header must contain the client host name. * * If your reverse proxy uses a different header name than "X-Forwarded-Host", * configure it via "setTrustedHeaderName()" with the "client-host" key. * * @return string * * @throws \UnexpectedValueException when the host name is invalid * * @api */ public function getHost() { if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) { $elements = explode(',', $host); $host = $elements[count($elements) - 1]; } elseif (!$host = $this->headers->get('HOST')) { if (!$host = $this->server->get('SERVER_NAME')) { $host = $this->server->get('SERVER_ADDR', ''); } } // trim and remove port number from host // host is lowercase as per RFC 952/2181 $host = strtolower(preg_replace('/:\d+$/', '', trim($host))); // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user) // check that it does not contain forbidden characters (see RFC 952 and RFC 2181) if ($host && !preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host)) { throw new \UnexpectedValueException(sprintf('Invalid Host "%s"', $host)); } if (count(self::$trustedHostPatterns) > 0) { // to avoid host header injection attacks, you should provide a list of trusted host patterns if (in_array($host, self::$trustedHosts)) { return $host; } foreach (self::$trustedHostPatterns as $pattern) { if (preg_match($pattern, $host)) { self::$trustedHosts[] = $host; return $host; } } throw new \UnexpectedValueException(sprintf('Untrusted Host "%s"', $host)); } return $host; } /** * Sets the request method. * * @param string $method * * @api */ public function setMethod($method) { $this->method = null; $this->server->set('REQUEST_METHOD', $method); } /** * Gets the request "intended" method. * * If the X-HTTP-Method-Override header is set, and if the method is a POST, * then it is used to determine the "real" intended HTTP method. * * The _method request parameter can also be used to determine the HTTP method, * but only if enableHttpMethodParameterOverride() has been called. * * The method is always an uppercased string. * * @return string The request method * * @api * * @see getRealMethod */ public function getMethod() { if (null === $this->method) { $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); if ('POST' === $this->method) { if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) { $this->method = strtoupper($method); } elseif (self::$httpMethodParameterOverride) { $this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST'))); } } } return $this->method; } /** * Gets the "real" request method. * * @return string The request method * * @see getMethod */ public function getRealMethod() { return strtoupper($this->server->get('REQUEST_METHOD', 'GET')); } /** * Gets the mime type associated with the format. * * @param string $format The format * * @return string The associated mime type (null if not found) * * @api */ public function getMimeType($format) { if (null === static::$formats) { static::initializeFormats(); } return isset(static::$formats[$format]) ? static::$formats[$format][0] : null; } /** * Gets the format associated with the mime type. * * @param string $mimeType The associated mime type * * @return string|null The format (null if not found) * * @api */ public function getFormat($mimeType) { if (false !== $pos = strpos($mimeType, ';')) { $mimeType = substr($mimeType, 0, $pos); } if (null === static::$formats) { static::initializeFormats(); } foreach (static::$formats as $format => $mimeTypes) { if (in_array($mimeType, (array) $mimeTypes)) { return $format; } } return null; } /** * Associates a format with mime types. * * @param string $format The format * @param string|array $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type) * * @api */ public function setFormat($format, $mimeTypes) { if (null === static::$formats) { static::initializeFormats(); } static::$formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes); } /** * Gets the request format. * * Here is the process to determine the format: * * * format defined by the user (with setRequestFormat()) * * _format request parameter * * $default * * @param string $default The default format * * @return string The request format * * @api */ public function getRequestFormat($default = 'html') { if (null === $this->format) { $this->format = $this->get('_format', $default); } return $this->format; } /** * Sets the request format. * * @param string $format The request format. * * @api */ public function setRequestFormat($format) { $this->format = $format; } /** * Gets the format associated with the request. * * @return string|null The format (null if no content type is present) * * @api */ public function getContentType() { return $this->getFormat($this->headers->get('CONTENT_TYPE')); } /** * Sets the default locale. * * @param string $locale * * @api */ public function setDefaultLocale($locale) { $this->defaultLocale = $locale; if (null === $this->locale) { $this->setPhpDefaultLocale($locale); } } /** * Sets the locale. * * @param string $locale * * @api */ public function setLocale($locale) { $this->setPhpDefaultLocale($this->locale = $locale); } /** * Get the locale. * * @return string */ public function getLocale() { return null === $this->locale ? $this->defaultLocale : $this->locale; } /** * Checks if the request method is of specified type. * * @param string $method Uppercase request method (GET, POST etc). * * @return Boolean */ public function isMethod($method) { return $this->getMethod() === strtoupper($method); } /** * Checks whether the method is safe or not. * * @return Boolean * * @api */ public function isMethodSafe() { return in_array($this->getMethod(), array('GET', 'HEAD')); } /** * Returns the request body content. * * @param Boolean $asResource If true, a resource will be returned * * @return string|resource The request body content or a resource to read the body stream. * * @throws \LogicException */ public function getContent($asResource = false) { if (false === $this->content || (true === $asResource && null !== $this->content)) { throw new \LogicException('getContent() can only be called once when using the resource return type.'); } if (true === $asResource) { $this->content = false; return fopen('php://input', 'rb'); } if (null === $this->content) { $this->content = file_get_contents('php://input'); } return $this->content; } /** * Gets the Etags. * * @return array The entity tags */ public function getETags() { return preg_split('/\s*,\s*/', $this->headers->get('if_none_match'), null, PREG_SPLIT_NO_EMPTY); } /** * @return Boolean */ public function isNoCache() { return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma'); } /** * Returns the preferred language. * * @param array $locales An array of ordered available locales * * @return string|null The preferred locale * * @api */ public function getPreferredLanguage(array $locales = null) { $preferredLanguages = $this->getLanguages(); if (empty($locales)) { return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null; } if (!$preferredLanguages) { return $locales[0]; } $extendedPreferredLanguages = array(); foreach ($preferredLanguages as $language) { $extendedPreferredLanguages[] = $language; if (false !== $position = strpos($language, '_')) { $superLanguage = substr($language, 0, $position); if (!in_array($superLanguage, $preferredLanguages)) { $extendedPreferredLanguages[] = $superLanguage; } } } $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales)); return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0]; } /** * Gets a list of languages acceptable by the client browser. * * @return array Languages ordered in the user browser preferences * * @api */ public function getLanguages() { if (null !== $this->languages) { return $this->languages; } $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all(); $this->languages = array(); foreach (array_keys($languages) as $lang) { if (strstr($lang, '-')) { $codes = explode('-', $lang); if ($codes[0] == 'i') { // Language not listed in ISO 639 that are not variants // of any listed language, which can be registered with the // i-prefix, such as i-cherokee if (count($codes) > 1) { $lang = $codes[1]; } } else { for ($i = 0, $max = count($codes); $i < $max; $i++) { if ($i == 0) { $lang = strtolower($codes[0]); } else { $lang .= '_'.strtoupper($codes[$i]); } } } } $this->languages[] = $lang; } return $this->languages; } /** * Gets a list of charsets acceptable by the client browser. * * @return array List of charsets in preferable order * * @api */ public function getCharsets() { if (null !== $this->charsets) { return $this->charsets; } return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all()); } /** * Gets a list of encodings acceptable by the client browser. * * @return array List of encodings in preferable order */ public function getEncodings() { if (null !== $this->encodings) { return $this->encodings; } return $this->encodings = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all()); } /** * Gets a list of content types acceptable by the client browser * * @return array List of content types in preferable order * * @api */ public function getAcceptableContentTypes() { if (null !== $this->acceptableContentTypes) { return $this->acceptableContentTypes; } return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all()); } /** * Returns true if the request is a XMLHttpRequest. * * It works if your JavaScript library set an X-Requested-With HTTP header. * It is known to work with common JavaScript frameworks: * @link http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript * * @return Boolean true if the request is an XMLHttpRequest, false otherwise * * @api */ public function isXmlHttpRequest() { return 'XMLHttpRequest' == $this->headers->get('X-Requested-With'); } /* * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24) * * Code subject to the new BSD license (http://framework.zend.com/license/new-bsd). * * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) */ protected function prepareRequestUri() { $requestUri = ''; if ($this->headers->has('X_ORIGINAL_URL')) { // IIS with Microsoft Rewrite Module $requestUri = $this->headers->get('X_ORIGINAL_URL'); $this->headers->remove('X_ORIGINAL_URL'); $this->server->remove('HTTP_X_ORIGINAL_URL'); $this->server->remove('UNENCODED_URL'); $this->server->remove('IIS_WasUrlRewritten'); } elseif ($this->headers->has('X_REWRITE_URL')) { // IIS with ISAPI_Rewrite $requestUri = $this->headers->get('X_REWRITE_URL'); $this->headers->remove('X_REWRITE_URL'); } elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') { // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) $requestUri = $this->server->get('UNENCODED_URL'); $this->server->remove('UNENCODED_URL'); $this->server->remove('IIS_WasUrlRewritten'); } elseif ($this->server->has('REQUEST_URI')) { $requestUri = $this->server->get('REQUEST_URI'); // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, only use URL path $schemeAndHttpHost = $this->getSchemeAndHttpHost(); if (strpos($requestUri, $schemeAndHttpHost) === 0) { $requestUri = substr($requestUri, strlen($schemeAndHttpHost)); } } elseif ($this->server->has('ORIG_PATH_INFO')) { // IIS 5.0, PHP as CGI $requestUri = $this->server->get('ORIG_PATH_INFO'); if ('' != $this->server->get('QUERY_STRING')) { $requestUri .= '?'.$this->server->get('QUERY_STRING'); } $this->server->remove('ORIG_PATH_INFO'); } // normalize the request URI to ease creating sub-requests from this request $this->server->set('REQUEST_URI', $requestUri); return $requestUri; } /** * Prepares the base URL. * * @return string */ protected function prepareBaseUrl() { $filename = basename($this->server->get('SCRIPT_FILENAME')); if (basename($this->server->get('SCRIPT_NAME')) === $filename) { $baseUrl = $this->server->get('SCRIPT_NAME'); } elseif (basename($this->server->get('PHP_SELF')) === $filename) { $baseUrl = $this->server->get('PHP_SELF'); } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) { $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility } else { // Backtrack up the script_filename to find the portion matching // php_self $path = $this->server->get('PHP_SELF', ''); $file = $this->server->get('SCRIPT_FILENAME', ''); $segs = explode('/', trim($file, '/')); $segs = array_reverse($segs); $index = 0; $last = count($segs); $baseUrl = ''; do { $seg = $segs[$index]; $baseUrl = '/'.$seg.$baseUrl; ++$index; } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos); } // Does the baseUrl have anything in common with the request_uri? $requestUri = $this->getRequestUri(); if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { // full $baseUrl matches return $prefix; } if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, dirname($baseUrl))) { // directory portion of $baseUrl matches return rtrim($prefix, '/'); } $truncatedRequestUri = $requestUri; if (false !== $pos = strpos($requestUri, '?')) { $truncatedRequestUri = substr($requestUri, 0, $pos); } $basename = basename($baseUrl); if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) { // no match whatsoever; set it blank return ''; } // If using mod_rewrite or ISAPI_Rewrite strip the script filename // out of baseUrl. $pos !== 0 makes sure it is not matching a value // from PATH_INFO or QUERY_STRING if (strlen($requestUri) >= strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && $pos !== 0) { $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl)); } return rtrim($baseUrl, '/'); } /** * Prepares the base path. * * @return string base path */ protected function prepareBasePath() { $filename = basename($this->server->get('SCRIPT_FILENAME')); $baseUrl = $this->getBaseUrl(); if (empty($baseUrl)) { return ''; } if (basename($baseUrl) === $filename) { $basePath = dirname($baseUrl); } else { $basePath = $baseUrl; } if ('\\' === DIRECTORY_SEPARATOR) { $basePath = str_replace('\\', '/', $basePath); } return rtrim($basePath, '/'); } /** * Prepares the path info. * * @return string path info */ protected function preparePathInfo() { $baseUrl = $this->getBaseUrl(); if (null === ($requestUri = $this->getRequestUri())) { return '/'; } $pathInfo = '/'; // Remove the query string from REQUEST_URI if ($pos = strpos($requestUri, '?')) { $requestUri = substr($requestUri, 0, $pos); } if (null !== $baseUrl && false === $pathInfo = substr($requestUri, strlen($baseUrl))) { // If substr() returns false then PATH_INFO is set to an empty string return '/'; } elseif (null === $baseUrl) { return $requestUri; } return (string) $pathInfo; } /** * Initializes HTTP request formats. */ protected static function initializeFormats() { static::$formats = array( 'html' => array('text/html', 'application/xhtml+xml'), 'txt' => array('text/plain'), 'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'), 'css' => array('text/css'), 'json' => array('application/json', 'application/x-json'), 'xml' => array('text/xml', 'application/xml', 'application/x-xml'), 'rdf' => array('application/rdf+xml'), 'atom' => array('application/atom+xml'), 'rss' => array('application/rss+xml'), ); } /** * Sets the default PHP locale. * * @param string $locale */ private function setPhpDefaultLocale($locale) { // if either the class Locale doesn't exist, or an exception is thrown when // setting the default locale, the intl module is not installed, and // the call can be ignored: try { if (class_exists('Locale', false)) { \Locale::setDefault($locale); } } catch (\Exception $e) { } } /* * Returns the prefix as encoded in the string when the string starts with * the given prefix, false otherwise. * * @param string $string The urlencoded string * @param string $prefix The prefix not encoded * * @return string|false The prefix as it is encoded in $string, or false */ private function getUrlencodedPrefix($string, $prefix) { if (0 !== strpos(rawurldecode($string), $prefix)) { return false; } $len = strlen($prefix); if (preg_match("#^(%[[:xdigit:]]{2}|.){{$len}}#", $string, $match)) { return $match[0]; } return false; } private static function createRequestFromFactory(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { if (self::$requestFactory) { $request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content); if (!$request instanceof Request) { throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.'); } return $request; } return new static($query, $request, $attributes, $cookies, $files, $server, $content); } } PK]6= HttpFoundation/IpUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Http utility functions. * * @author Fabien Potencier */ class IpUtils { /** * This class should not be instantiated */ private function __construct() {} /** * Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets * * @param string $requestIp IP to check * @param string|array $ips List of IPs or subnets (can be a string if only a single one) * * @return boolean Whether the IP is valid */ public static function checkIp($requestIp, $ips) { if (!is_array($ips)) { $ips = array($ips); } $method = false !== strpos($requestIp, ':') ? 'checkIp6': 'checkIp4'; foreach ($ips as $ip) { if (self::$method($requestIp, $ip)) { return true; } } return false; } /** * Compares two IPv4 addresses. * In case a subnet is given, it checks if it contains the request IP. * * @param string $requestIp IPv4 address to check * @param string $ip IPv4 address or subnet in CIDR notation * * @return boolean Whether the IP is valid */ public static function checkIp4($requestIp, $ip) { if (false !== strpos($ip, '/')) { list($address, $netmask) = explode('/', $ip, 2); if ($netmask < 1 || $netmask > 32) { return false; } } else { $address = $ip; $netmask = 32; } return 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); } /** * Compares two IPv6 addresses. * In case a subnet is given, it checks if it contains the request IP. * * @author David Soria Parra * @see https://github.com/dsp/v6tools * * @param string $requestIp IPv6 address to check * @param string $ip IPv6 address or subnet in CIDR notation * * @return boolean Whether the IP is valid * * @throws \RuntimeException When IPV6 support is not enabled */ public static function checkIp6($requestIp, $ip) { if (!((extension_loaded('sockets') && defined('AF_INET6')) || @inet_pton('::1'))) { throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); } if (false !== strpos($ip, '/')) { list($address, $netmask) = explode('/', $ip, 2); if ($netmask < 1 || $netmask > 128) { return false; } } else { $address = $ip; $netmask = 128; } $bytesAddr = unpack("n*", inet_pton($address)); $bytesTest = unpack("n*", inet_pton($requestIp)); for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; $i++) { $left = $netmask - 16 * ($i-1); $left = ($left <= 16) ? $left : 16; $mask = ~(0xffff >> $left) & 0xffff; if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { return false; } } return true; } } PK]d}޷%%%HttpFoundation/BinaryFileResponse.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\Exception\FileException; /** * BinaryFileResponse represents an HTTP response delivering a file. * * @author Niklas Fiekas * @author stealth35 * @author Igor Wiedler * @author Jordan Alliot * @author Sergey Linnik */ class BinaryFileResponse extends Response { protected static $trustXSendfileTypeHeader = false; protected $file; protected $offset; protected $maxlen; /** * Constructor. * * @param \SplFileInfo|string $file The file to stream * @param integer $status The response status code * @param array $headers An array of response headers * @param boolean $public Files are public by default * @param null|string $contentDisposition The type of Content-Disposition to set automatically with the filename * @param boolean $autoEtag Whether the ETag header should be automatically set * @param boolean $autoLastModified Whether the Last-Modified header should be automatically set */ public function __construct($file, $status = 200, $headers = array(), $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) { parent::__construct(null, $status, $headers); $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified); if ($public) { $this->setPublic(); } } /** * @param \SplFileInfo|string $file The file to stream * @param integer $status The response status code * @param array $headers An array of response headers * @param boolean $public Files are public by default * @param null|string $contentDisposition The type of Content-Disposition to set automatically with the filename * @param boolean $autoEtag Whether the ETag header should be automatically set * @param boolean $autoLastModified Whether the Last-Modified header should be automatically set */ public static function create($file = null, $status = 200, $headers = array(), $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) { return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified); } /** * Sets the file to stream. * * @param \SplFileInfo|string $file The file to stream * @param string $contentDisposition * @param Boolean $autoEtag * @param Boolean $autoLastModified * * @return BinaryFileResponse * * @throws FileException */ public function setFile($file, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) { $file = new File((string) $file); if (!$file->isReadable()) { throw new FileException('File must be readable.'); } $this->file = $file; if ($autoEtag) { $this->setAutoEtag(); } if ($autoLastModified) { $this->setAutoLastModified(); } if ($contentDisposition) { $this->setContentDisposition($contentDisposition); } return $this; } /** * Gets the file. * * @return File The file to stream */ public function getFile() { return $this->file; } /** * Automatically sets the Last-Modified header according the file modification date. */ public function setAutoLastModified() { $this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime())); return $this; } /** * Automatically sets the ETag header according to the checksum of the file. */ public function setAutoEtag() { $this->setEtag(sha1_file($this->file->getPathname())); return $this; } /** * Sets the Content-Disposition header with the given filename. * * @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT * @param string $filename Optionally use this filename instead of the real name of the file * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename * * @return BinaryFileResponse */ public function setContentDisposition($disposition, $filename = '', $filenameFallback = '') { if ($filename === '') { $filename = $this->file->getFilename(); } $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback); $this->headers->set('Content-Disposition', $dispositionHeader); return $this; } /** * {@inheritdoc} */ public function prepare(Request $request) { $this->headers->set('Content-Length', $this->file->getSize()); $this->headers->set('Accept-Ranges', 'bytes'); $this->headers->set('Content-Transfer-Encoding', 'binary'); if (!$this->headers->has('Content-Type')) { $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream'); } if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { $this->setProtocolVersion('1.1'); } $this->ensureIEOverSSLCompatibility($request); $this->offset = 0; $this->maxlen = -1; if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) { // Use X-Sendfile, do not send any content. $type = $request->headers->get('X-Sendfile-Type'); $path = $this->file->getRealPath(); if (strtolower($type) == 'x-accel-redirect') { // Do X-Accel-Mapping substitutions. foreach (explode(',', $request->headers->get('X-Accel-Mapping', '')) as $mapping) { $mapping = explode('=', $mapping, 2); if (2 == count($mapping)) { $location = trim($mapping[0]); $pathPrefix = trim($mapping[1]); if (substr($path, 0, strlen($pathPrefix)) == $pathPrefix) { $path = $location.substr($path, strlen($pathPrefix)); break; } } } } $this->headers->set($type, $path); $this->maxlen = 0; } elseif ($request->headers->has('Range')) { // Process the range headers. if (!$request->headers->has('If-Range') || $this->getEtag() == $request->headers->get('If-Range')) { $range = $request->headers->get('Range'); $fileSize = $this->file->getSize(); list($start, $end) = explode('-', substr($range, 6), 2) + array(0); $end = ('' === $end) ? $fileSize - 1 : (int) $end; if ('' === $start) { $start = $fileSize - $end; $end = $fileSize - 1; } else { $start = (int) $start; } if ($start <= $end) { if ($start < 0 || $end > $fileSize - 1) { $this->setStatusCode(416); } elseif ($start !== 0 || $end !== $fileSize - 1) { $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1; $this->offset = $start; $this->setStatusCode(206); $this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize)); $this->headers->set('Content-Length', $end - $start + 1); } } } } return $this; } /** * Sends the file. */ public function sendContent() { if (!$this->isSuccessful()) { parent::sendContent(); return; } if (0 === $this->maxlen) { return; } $out = fopen('php://output', 'wb'); $file = fopen($this->file->getPathname(), 'rb'); stream_copy_to_stream($file, $out, $this->maxlen, $this->offset); fclose($out); fclose($file); } /** * {@inheritdoc} * * @throws \LogicException when the content is not null */ public function setContent($content) { if (null !== $content) { throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.'); } } /** * {@inheritdoc} * * @return false */ public function getContent() { return false; } /** * Trust X-Sendfile-Type header. */ public static function trustXSendfileTypeHeader() { self::$trustXSendfileTypeHeader = true; } } PK]1y*HttpFoundation/RequestMatcherInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * RequestMatcherInterface is an interface for strategies to match a Request. * * @author Fabien Potencier * * @api */ interface RequestMatcherInterface { /** * Decides whether the rule(s) implemented by the strategy matches the supplied request. * * @param Request $request The request to check for a match * * @return Boolean true if the request matches, false otherwise * * @api */ public function matches(Request $request); } PK]Vkb33#HttpFoundation/AcceptHeaderItem.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Represents an Accept-* header item. * * @author Jean-François Simon */ class AcceptHeaderItem { /** * @var string */ private $value; /** * @var float */ private $quality = 1.0; /** * @var int */ private $index = 0; /** * @var array */ private $attributes = array(); /** * Constructor. * * @param string $value * @param array $attributes */ public function __construct($value, array $attributes = array()) { $this->value = $value; foreach ($attributes as $name => $value) { $this->setAttribute($name, $value); } } /** * Builds an AcceptHeaderInstance instance from a string. * * @param string $itemValue * * @return AcceptHeaderItem */ public static function fromString($itemValue) { $bits = preg_split('/\s*(?:;*("[^"]+");*|;*(\'[^\']+\');*|;+)\s*/', $itemValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); $value = array_shift($bits); $attributes = array(); $lastNullAttribute = null; foreach ($bits as $bit) { if (($start = substr($bit, 0, 1)) === ($end = substr($bit, -1)) && ($start === '"' || $start === '\'')) { $attributes[$lastNullAttribute] = substr($bit, 1, -1); } elseif ('=' === $end) { $lastNullAttribute = $bit = substr($bit, 0, -1); $attributes[$bit] = null; } else { $parts = explode('=', $bit); $attributes[$parts[0]] = isset($parts[1]) && strlen($parts[1]) > 0 ? $parts[1] : ''; } } return new self(($start = substr($value, 0, 1)) === ($end = substr($value, -1)) && ($start === '"' || $start === '\'') ? substr($value, 1, -1) : $value, $attributes); } /** * Returns header value's string representation. * * @return string */ public function __toString() { $string = $this->value.($this->quality < 1 ? ';q='.$this->quality : ''); if (count($this->attributes) > 0) { $string .= ';'.implode(';', array_map(function ($name, $value) { return sprintf(preg_match('/[,;=]/', $value) ? '%s="%s"' : '%s=%s', $name, $value); }, array_keys($this->attributes), $this->attributes)); } return $string; } /** * Set the item value. * * @param string $value * * @return AcceptHeaderItem */ public function setValue($value) { $this->value = $value; return $this; } /** * Returns the item value. * * @return string */ public function getValue() { return $this->value; } /** * Set the item quality. * * @param float $quality * * @return AcceptHeaderItem */ public function setQuality($quality) { $this->quality = $quality; return $this; } /** * Returns the item quality. * * @return float */ public function getQuality() { return $this->quality; } /** * Set the item index. * * @param int $index * * @return AcceptHeaderItem */ public function setIndex($index) { $this->index = $index; return $this; } /** * Returns the item index. * * @return int */ public function getIndex() { return $this->index; } /** * Tests if an attribute exists. * * @param string $name * * @return Boolean */ public function hasAttribute($name) { return isset($this->attributes[$name]); } /** * Returns an attribute by its name. * * @param string $name * @param mixed $default * * @return mixed */ public function getAttribute($name, $default = null) { return isset($this->attributes[$name]) ? $this->attributes[$name] : $default; } /** * Returns all attributes. * * @return array */ public function getAttributes() { return $this->attributes; } /** * Set an attribute. * * @param string $name * @param string $value * * @return AcceptHeaderItem */ public function setAttribute($name, $value) { if ('q' === $name) { $this->quality = (float) $value; } else { $this->attributes[$name] = (string) $value; } return $this; } } PK]nOO+HttpFoundation/ExpressionRequestMatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; /** * ExpressionRequestMatcher uses an expression to match a Request. * * @author Fabien Potencier */ class ExpressionRequestMatcher extends RequestMatcher { private $language; private $expression; public function setExpression(ExpressionLanguage $language, $expression) { $this->language = $language; $this->expression = $expression; } public function matches(Request $request) { if (!$this->language) { throw new \LogicException('Unable to match the request as the expression language is not available.'); } return $this->language->evaluate($this->expression, array( 'request' => $request, 'method' => $request->getMethod(), 'path' => rawurldecode($request->getPathInfo()), 'host' => $request->getHost(), 'ip' => $request->getClientIp(), 'attributes' => $request->attributes->all(), )) && parent::matches($request); } } PK]}xxHttpFoundation/ServerBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * ServerBag is a container for HTTP headers from the $_SERVER variable. * * @author Fabien Potencier * @author Bulat Shakirzyanov * @author Robert Kiss */ class ServerBag extends ParameterBag { /** * Gets the HTTP headers. * * @return array */ public function getHeaders() { $headers = array(); $contentHeaders = array('CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true); foreach ($this->parameters as $key => $value) { if (0 === strpos($key, 'HTTP_')) { $headers[substr($key, 5)] = $value; } // CONTENT_* are not prefixed with HTTP_ elseif (isset($contentHeaders[$key])) { $headers[$key] = $value; } } if (isset($this->parameters['PHP_AUTH_USER'])) { $headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER']; $headers['PHP_AUTH_PW'] = isset($this->parameters['PHP_AUTH_PW']) ? $this->parameters['PHP_AUTH_PW'] : ''; } else { /* * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default * For this workaround to work, add these lines to your .htaccess file: * RewriteCond %{HTTP:Authorization} ^(.+)$ * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] * * A sample .htaccess file: * RewriteEngine On * RewriteCond %{HTTP:Authorization} ^(.+)$ * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] * RewriteCond %{REQUEST_FILENAME} !-f * RewriteRule ^(.*)$ app.php [QSA,L] */ $authorizationHeader = null; if (isset($this->parameters['HTTP_AUTHORIZATION'])) { $authorizationHeader = $this->parameters['HTTP_AUTHORIZATION']; } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) { $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION']; } if (null !== $authorizationHeader) { if (0 === stripos($authorizationHeader, 'basic')) { // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic $exploded = explode(':', base64_decode(substr($authorizationHeader, 6))); if (count($exploded) == 2) { list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded; } } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest'))) { // In some circumstances PHP_AUTH_DIGEST needs to be set $headers['PHP_AUTH_DIGEST'] = $authorizationHeader; $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader; } } } // PHP_AUTH_USER/PHP_AUTH_PW if (isset($headers['PHP_AUTH_USER'])) { $headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']); } elseif (isset($headers['PHP_AUTH_DIGEST'])) { $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST']; } return $headers; } } PK]FHttpFoundation/Cookie.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Represents a cookie * * @author Johannes M. Schmitt * * @api */ class Cookie { protected $name; protected $value; protected $domain; protected $expire; protected $path; protected $secure; protected $httpOnly; /** * Constructor. * * @param string $name The name of the cookie * @param string $value The value of the cookie * @param integer|string|\DateTime $expire The time the cookie expires * @param string $path The path on the server in which the cookie will be available on * @param string $domain The domain that the cookie is available to * @param Boolean $secure Whether the cookie should only be transmitted over a secure HTTPS connection from the client * @param Boolean $httpOnly Whether the cookie will be made accessible only through the HTTP protocol * * @throws \InvalidArgumentException * * @api */ public function __construct($name, $value = null, $expire = 0, $path = '/', $domain = null, $secure = false, $httpOnly = true) { // from PHP source code if (preg_match("/[=,; \t\r\n\013\014]/", $name)) { throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); } if (empty($name)) { throw new \InvalidArgumentException('The cookie name cannot be empty.'); } // convert expiration time to a Unix timestamp if ($expire instanceof \DateTime) { $expire = $expire->format('U'); } elseif (!is_numeric($expire)) { $expire = strtotime($expire); if (false === $expire || -1 === $expire) { throw new \InvalidArgumentException('The cookie expiration time is not valid.'); } } $this->name = $name; $this->value = $value; $this->domain = $domain; $this->expire = $expire; $this->path = empty($path) ? '/' : $path; $this->secure = (Boolean) $secure; $this->httpOnly = (Boolean) $httpOnly; } /** * Returns the cookie as a string. * * @return string The cookie */ public function __toString() { $str = urlencode($this->getName()).'='; if ('' === (string) $this->getValue()) { $str .= 'deleted; expires='.gmdate("D, d-M-Y H:i:s T", time() - 31536001); } else { $str .= urlencode($this->getValue()); if ($this->getExpiresTime() !== 0) { $str .= '; expires='.gmdate("D, d-M-Y H:i:s T", $this->getExpiresTime()); } } if ($this->path) { $str .= '; path='.$this->path; } if ($this->getDomain()) { $str .= '; domain='.$this->getDomain(); } if (true === $this->isSecure()) { $str .= '; secure'; } if (true === $this->isHttpOnly()) { $str .= '; httponly'; } return $str; } /** * Gets the name of the cookie. * * @return string * * @api */ public function getName() { return $this->name; } /** * Gets the value of the cookie. * * @return string * * @api */ public function getValue() { return $this->value; } /** * Gets the domain that the cookie is available to. * * @return string * * @api */ public function getDomain() { return $this->domain; } /** * Gets the time the cookie expires. * * @return integer * * @api */ public function getExpiresTime() { return $this->expire; } /** * Gets the path on the server in which the cookie will be available on. * * @return string * * @api */ public function getPath() { return $this->path; } /** * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client. * * @return Boolean * * @api */ public function isSecure() { return $this->secure; } /** * Checks whether the cookie will be made accessible only through the HTTP protocol. * * @return Boolean * * @api */ public function isHttpOnly() { return $this->httpOnly; } /** * Whether this cookie is about to be cleared * * @return Boolean * * @api */ public function isCleared() { return $this->expire < time(); } } PK]ގ##$HttpFoundation/File/UploadedFile.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File; use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser; /** * A file uploaded through a form. * * @author Bernhard Schussek * @author Florian Eckerstorfer * @author Fabien Potencier * * @api */ class UploadedFile extends File { /** * Whether the test mode is activated. * * Local files are used in test mode hence the code should not enforce HTTP uploads. * * @var Boolean */ private $test = false; /** * The original name of the uploaded file. * * @var string */ private $originalName; /** * The mime type provided by the uploader. * * @var string */ private $mimeType; /** * The file size provided by the uploader. * * @var string */ private $size; /** * The UPLOAD_ERR_XXX constant provided by the uploader. * * @var integer */ private $error; /** * Accepts the information of the uploaded file as provided by the PHP global $_FILES. * * The file object is only created when the uploaded file is valid (i.e. when the * isValid() method returns true). Otherwise the only methods that could be called * on an UploadedFile instance are: * * * getClientOriginalName, * * getClientMimeType, * * isValid, * * getError. * * Calling any other method on an non-valid instance will cause an unpredictable result. * * @param string $path The full temporary path to the file * @param string $originalName The original file name * @param string $mimeType The type of the file as provided by PHP * @param integer $size The file size * @param integer $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants) * @param Boolean $test Whether the test mode is active * * @throws FileException If file_uploads is disabled * @throws FileNotFoundException If the file does not exist * * @api */ public function __construct($path, $originalName, $mimeType = null, $size = null, $error = null, $test = false) { $this->originalName = $this->getName($originalName); $this->mimeType = $mimeType ?: 'application/octet-stream'; $this->size = $size; $this->error = $error ?: UPLOAD_ERR_OK; $this->test = (Boolean) $test; parent::__construct($path, UPLOAD_ERR_OK === $this->error); } /** * Returns the original file name. * * It is extracted from the request from which the file has been uploaded. * Then it should not be considered as a safe value. * * @return string|null The original name * * @api */ public function getClientOriginalName() { return $this->originalName; } /** * Returns the original file extension * * It is extracted from the original file name that was uploaded. * Then it should not be considered as a safe value. * * @return string The extension */ public function getClientOriginalExtension() { return pathinfo($this->originalName, PATHINFO_EXTENSION); } /** * Returns the file mime type. * * The client mime type is extracted from the request from which the file * was uploaded, so it should not be considered as a safe value. * * For a trusted mime type, use getMimeType() instead (which guesses the mime * type based on the file content). * * @return string|null The mime type * * @see getMimeType * * @api */ public function getClientMimeType() { return $this->mimeType; } /** * Returns the extension based on the client mime type. * * If the mime type is unknown, returns null. * * This method uses the mime type as guessed by getClientMimeType() * to guess the file extension. As such, the extension returned * by this method cannot be trusted. * * For a trusted extension, use guessExtension() instead (which guesses * the extension based on the guessed mime type for the file). * * @return string|null The guessed extension or null if it cannot be guessed * * @see guessExtension() * @see getClientMimeType() */ public function guessClientExtension() { $type = $this->getClientMimeType(); $guesser = ExtensionGuesser::getInstance(); return $guesser->guess($type); } /** * Returns the file size. * * It is extracted from the request from which the file has been uploaded. * Then it should not be considered as a safe value. * * @return integer|null The file size * * @api */ public function getClientSize() { return $this->size; } /** * Returns the upload error. * * If the upload was successful, the constant UPLOAD_ERR_OK is returned. * Otherwise one of the other UPLOAD_ERR_XXX constants is returned. * * @return integer The upload error * * @api */ public function getError() { return $this->error; } /** * Returns whether the file was uploaded successfully. * * @return Boolean True if the file has been uploaded with HTTP and no error occurred. * * @api */ public function isValid() { $isOk = $this->error === UPLOAD_ERR_OK; return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname()); } /** * Moves the file to a new location. * * @param string $directory The destination folder * @param string $name The new file name * * @return File A File object representing the new file * * @throws FileException if, for any reason, the file could not have been moved * * @api */ public function move($directory, $name = null) { if ($this->isValid()) { if ($this->test) { return parent::move($directory, $name); } $target = $this->getTargetFile($directory, $name); if (!@move_uploaded_file($this->getPathname(), $target)) { $error = error_get_last(); throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message']))); } @chmod($target, 0666 & ~umask()); return $target; } throw new FileException($this->getErrorMessage()); } /** * Returns the maximum size of an uploaded file as configured in php.ini * * @return int The maximum size of an uploaded file in bytes */ public static function getMaxFilesize() { $iniMax = strtolower(ini_get('upload_max_filesize')); if ('' === $iniMax) { return PHP_INT_MAX; } $max = ltrim($iniMax, '+'); if (0 === strpos($max, '0x')) { $max = intval($max, 16); } elseif (0 === strpos($max, '0')) { $max = intval($max, 8); } else { $max = intval($max); } switch (substr($iniMax, -1)) { case 't': $max *= 1024; case 'g': $max *= 1024; case 'm': $max *= 1024; case 'k': $max *= 1024; } return $max; } /** * Returns an informative upload error message. * * @return string The error message regarding the specified error code */ public function getErrorMessage() { static $errors = array( UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d kb).', UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.', UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.', UPLOAD_ERR_NO_FILE => 'No file was uploaded.', UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.', UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.', UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.', ); $errorCode = $this->error; $maxFilesize = $errorCode === UPLOAD_ERR_INI_SIZE ? self::getMaxFilesize() / 1024 : 0; $message = isset($errors[$errorCode]) ? $errors[$errorCode] : 'The file "%s" was not uploaded due to an unknown error.'; return sprintf($message, $this->getClientOriginalName(), $maxFilesize); } } PK]60HttpFoundation/File/MimeType/MimeTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; /** * A singleton mime type guesser. * * By default, all mime type guessers provided by the framework are installed * (if available on the current OS/PHP setup). * * You can register custom guessers by calling the register() method on the * singleton instance. Custom guessers are always called before any default ones. * * $guesser = MimeTypeGuesser::getInstance(); * $guesser->register(new MyCustomMimeTypeGuesser()); * * If you want to change the order of the default guessers, just re-register your * preferred one as a custom one. The last registered guesser is preferred over * previously registered ones. * * Re-registering a built-in guesser also allows you to configure it: * * $guesser = MimeTypeGuesser::getInstance(); * $guesser->register(new FileinfoMimeTypeGuesser('/path/to/magic/file')); * * @author Bernhard Schussek */ class MimeTypeGuesser implements MimeTypeGuesserInterface { /** * The singleton instance * * @var MimeTypeGuesser */ private static $instance = null; /** * All registered MimeTypeGuesserInterface instances * * @var array */ protected $guessers = array(); /** * Returns the singleton instance * * @return MimeTypeGuesser */ public static function getInstance() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; } /** * Registers all natively provided mime type guessers */ private function __construct() { if (FileBinaryMimeTypeGuesser::isSupported()) { $this->register(new FileBinaryMimeTypeGuesser()); } if (FileinfoMimeTypeGuesser::isSupported()) { $this->register(new FileinfoMimeTypeGuesser()); } } /** * Registers a new mime type guesser * * When guessing, this guesser is preferred over previously registered ones. * * @param MimeTypeGuesserInterface $guesser */ public function register(MimeTypeGuesserInterface $guesser) { array_unshift($this->guessers, $guesser); } /** * Tries to guess the mime type of the given file * * The file is passed to each registered mime type guesser in reverse order * of their registration (last registered is queried first). Once a guesser * returns a value that is not NULL, this method terminates and returns the * value. * * @param string $path The path to the file * * @return string The mime type or NULL, if none could be guessed * * @throws \LogicException * @throws FileNotFoundException * @throws AccessDeniedException */ public function guess($path) { if (!is_file($path)) { throw new FileNotFoundException($path); } if (!is_readable($path)) { throw new AccessDeniedException($path); } if (!$this->guessers) { throw new \LogicException('Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)'); } foreach ($this->guessers as $guesser) { if (null !== $mimeType = $guesser->guess($path)) { return $mimeType; } } } } PK] L9HttpFoundation/File/MimeType/MimeTypeGuesserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; /** * Guesses the mime type of a file * * @author Bernhard Schussek */ interface MimeTypeGuesserInterface { /** * Guesses the mime type of the file with the given path. * * @param string $path The path to the file * * @return string The mime type or NULL, if none could be guessed * * @throws FileNotFoundException If the file does not exist * @throws AccessDeniedException If the file could not be read */ public function guess($path); } PK]wnMM9HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; /** * Provides a best-guess mapping of mime type to file extension. */ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface { /** * A map of mime types and their default extensions. * * This list has been placed under the public domain by the Apache HTTPD project. * This list has been updated from upstream on 2013-04-23. * * @see http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types * * @var array */ protected $defaultExtensions = array( 'application/andrew-inset' => 'ez', 'application/applixware' => 'aw', 'application/atom+xml' => 'atom', 'application/atomcat+xml' => 'atomcat', 'application/atomsvc+xml' => 'atomsvc', 'application/ccxml+xml' => 'ccxml', 'application/cdmi-capability' => 'cdmia', 'application/cdmi-container' => 'cdmic', 'application/cdmi-domain' => 'cdmid', 'application/cdmi-object' => 'cdmio', 'application/cdmi-queue' => 'cdmiq', 'application/cu-seeme' => 'cu', 'application/davmount+xml' => 'davmount', 'application/docbook+xml' => 'dbk', 'application/dssc+der' => 'dssc', 'application/dssc+xml' => 'xdssc', 'application/ecmascript' => 'ecma', 'application/emma+xml' => 'emma', 'application/epub+zip' => 'epub', 'application/exi' => 'exi', 'application/font-tdpfr' => 'pfr', 'application/gml+xml' => 'gml', 'application/gpx+xml' => 'gpx', 'application/gxf' => 'gxf', 'application/hyperstudio' => 'stk', 'application/inkml+xml' => 'ink', 'application/ipfix' => 'ipfix', 'application/java-archive' => 'jar', 'application/java-serialized-object' => 'ser', 'application/java-vm' => 'class', 'application/javascript' => 'js', 'application/json' => 'json', 'application/jsonml+json' => 'jsonml', 'application/lost+xml' => 'lostxml', 'application/mac-binhex40' => 'hqx', 'application/mac-compactpro' => 'cpt', 'application/mads+xml' => 'mads', 'application/marc' => 'mrc', 'application/marcxml+xml' => 'mrcx', 'application/mathematica' => 'ma', 'application/mathml+xml' => 'mathml', 'application/mbox' => 'mbox', 'application/mediaservercontrol+xml' => 'mscml', 'application/metalink+xml' => 'metalink', 'application/metalink4+xml' => 'meta4', 'application/mets+xml' => 'mets', 'application/mods+xml' => 'mods', 'application/mp21' => 'm21', 'application/mp4' => 'mp4s', 'application/msword' => 'doc', 'application/mxf' => 'mxf', 'application/octet-stream' => 'bin', 'application/oda' => 'oda', 'application/oebps-package+xml' => 'opf', 'application/ogg' => 'ogx', 'application/omdoc+xml' => 'omdoc', 'application/onenote' => 'onetoc', 'application/oxps' => 'oxps', 'application/patch-ops-error+xml' => 'xer', 'application/pdf' => 'pdf', 'application/pgp-encrypted' => 'pgp', 'application/pgp-signature' => 'asc', 'application/pics-rules' => 'prf', 'application/pkcs10' => 'p10', 'application/pkcs7-mime' => 'p7m', 'application/pkcs7-signature' => 'p7s', 'application/pkcs8' => 'p8', 'application/pkix-attr-cert' => 'ac', 'application/pkix-cert' => 'cer', 'application/pkix-crl' => 'crl', 'application/pkix-pkipath' => 'pkipath', 'application/pkixcmp' => 'pki', 'application/pls+xml' => 'pls', 'application/postscript' => 'ai', 'application/prs.cww' => 'cww', 'application/pskc+xml' => 'pskcxml', 'application/rdf+xml' => 'rdf', 'application/reginfo+xml' => 'rif', 'application/relax-ng-compact-syntax' => 'rnc', 'application/resource-lists+xml' => 'rl', 'application/resource-lists-diff+xml' => 'rld', 'application/rls-services+xml' => 'rs', 'application/rpki-ghostbusters' => 'gbr', 'application/rpki-manifest' => 'mft', 'application/rpki-roa' => 'roa', 'application/rsd+xml' => 'rsd', 'application/rss+xml' => 'rss', 'application/rtf' => 'rtf', 'application/sbml+xml' => 'sbml', 'application/scvp-cv-request' => 'scq', 'application/scvp-cv-response' => 'scs', 'application/scvp-vp-request' => 'spq', 'application/scvp-vp-response' => 'spp', 'application/sdp' => 'sdp', 'application/set-payment-initiation' => 'setpay', 'application/set-registration-initiation' => 'setreg', 'application/shf+xml' => 'shf', 'application/smil+xml' => 'smi', 'application/sparql-query' => 'rq', 'application/sparql-results+xml' => 'srx', 'application/srgs' => 'gram', 'application/srgs+xml' => 'grxml', 'application/sru+xml' => 'sru', 'application/ssdl+xml' => 'ssdl', 'application/ssml+xml' => 'ssml', 'application/tei+xml' => 'tei', 'application/thraud+xml' => 'tfi', 'application/timestamped-data' => 'tsd', 'application/vnd.3gpp.pic-bw-large' => 'plb', 'application/vnd.3gpp.pic-bw-small' => 'psb', 'application/vnd.3gpp.pic-bw-var' => 'pvb', 'application/vnd.3gpp2.tcap' => 'tcap', 'application/vnd.3m.post-it-notes' => 'pwn', 'application/vnd.accpac.simply.aso' => 'aso', 'application/vnd.accpac.simply.imp' => 'imp', 'application/vnd.acucobol' => 'acu', 'application/vnd.acucorp' => 'atc', 'application/vnd.adobe.air-application-installer-package+zip' => 'air', 'application/vnd.adobe.formscentral.fcdt' => 'fcdt', 'application/vnd.adobe.fxp' => 'fxp', 'application/vnd.adobe.xdp+xml' => 'xdp', 'application/vnd.adobe.xfdf' => 'xfdf', 'application/vnd.ahead.space' => 'ahead', 'application/vnd.airzip.filesecure.azf' => 'azf', 'application/vnd.airzip.filesecure.azs' => 'azs', 'application/vnd.amazon.ebook' => 'azw', 'application/vnd.americandynamics.acc' => 'acc', 'application/vnd.amiga.ami' => 'ami', 'application/vnd.android.package-archive' => 'apk', 'application/vnd.anser-web-certificate-issue-initiation' => 'cii', 'application/vnd.anser-web-funds-transfer-initiation' => 'fti', 'application/vnd.antix.game-component' => 'atx', 'application/vnd.apple.installer+xml' => 'mpkg', 'application/vnd.apple.mpegurl' => 'm3u8', 'application/vnd.aristanetworks.swi' => 'swi', 'application/vnd.astraea-software.iota' => 'iota', 'application/vnd.audiograph' => 'aep', 'application/vnd.blueice.multipass' => 'mpm', 'application/vnd.bmi' => 'bmi', 'application/vnd.businessobjects' => 'rep', 'application/vnd.chemdraw+xml' => 'cdxml', 'application/vnd.chipnuts.karaoke-mmd' => 'mmd', 'application/vnd.cinderella' => 'cdy', 'application/vnd.claymore' => 'cla', 'application/vnd.cloanto.rp9' => 'rp9', 'application/vnd.clonk.c4group' => 'c4g', 'application/vnd.cluetrust.cartomobile-config' => 'c11amc', 'application/vnd.cluetrust.cartomobile-config-pkg' => 'c11amz', 'application/vnd.commonspace' => 'csp', 'application/vnd.contact.cmsg' => 'cdbcmsg', 'application/vnd.cosmocaller' => 'cmc', 'application/vnd.crick.clicker' => 'clkx', 'application/vnd.crick.clicker.keyboard' => 'clkk', 'application/vnd.crick.clicker.palette' => 'clkp', 'application/vnd.crick.clicker.template' => 'clkt', 'application/vnd.crick.clicker.wordbank' => 'clkw', 'application/vnd.criticaltools.wbs+xml' => 'wbs', 'application/vnd.ctc-posml' => 'pml', 'application/vnd.cups-ppd' => 'ppd', 'application/vnd.curl.car' => 'car', 'application/vnd.curl.pcurl' => 'pcurl', 'application/vnd.dart' => 'dart', 'application/vnd.data-vision.rdz' => 'rdz', 'application/vnd.dece.data' => 'uvf', 'application/vnd.dece.ttml+xml' => 'uvt', 'application/vnd.dece.unspecified' => 'uvx', 'application/vnd.dece.zip' => 'uvz', 'application/vnd.denovo.fcselayout-link' => 'fe_launch', 'application/vnd.dna' => 'dna', 'application/vnd.dolby.mlp' => 'mlp', 'application/vnd.dpgraph' => 'dpg', 'application/vnd.dreamfactory' => 'dfac', 'application/vnd.ds-keypoint' => 'kpxx', 'application/vnd.dvb.ait' => 'ait', 'application/vnd.dvb.service' => 'svc', 'application/vnd.dynageo' => 'geo', 'application/vnd.ecowin.chart' => 'mag', 'application/vnd.enliven' => 'nml', 'application/vnd.epson.esf' => 'esf', 'application/vnd.epson.msf' => 'msf', 'application/vnd.epson.quickanime' => 'qam', 'application/vnd.epson.salt' => 'slt', 'application/vnd.epson.ssf' => 'ssf', 'application/vnd.eszigno3+xml' => 'es3', 'application/vnd.ezpix-album' => 'ez2', 'application/vnd.ezpix-package' => 'ez3', 'application/vnd.fdf' => 'fdf', 'application/vnd.fdsn.mseed' => 'mseed', 'application/vnd.fdsn.seed' => 'seed', 'application/vnd.flographit' => 'gph', 'application/vnd.fluxtime.clip' => 'ftc', 'application/vnd.framemaker' => 'fm', 'application/vnd.frogans.fnc' => 'fnc', 'application/vnd.frogans.ltf' => 'ltf', 'application/vnd.fsc.weblaunch' => 'fsc', 'application/vnd.fujitsu.oasys' => 'oas', 'application/vnd.fujitsu.oasys2' => 'oa2', 'application/vnd.fujitsu.oasys3' => 'oa3', 'application/vnd.fujitsu.oasysgp' => 'fg5', 'application/vnd.fujitsu.oasysprs' => 'bh2', 'application/vnd.fujixerox.ddd' => 'ddd', 'application/vnd.fujixerox.docuworks' => 'xdw', 'application/vnd.fujixerox.docuworks.binder' => 'xbd', 'application/vnd.fuzzysheet' => 'fzs', 'application/vnd.genomatix.tuxedo' => 'txd', 'application/vnd.geogebra.file' => 'ggb', 'application/vnd.geogebra.tool' => 'ggt', 'application/vnd.geometry-explorer' => 'gex', 'application/vnd.geonext' => 'gxt', 'application/vnd.geoplan' => 'g2w', 'application/vnd.geospace' => 'g3w', 'application/vnd.gmx' => 'gmx', 'application/vnd.google-earth.kml+xml' => 'kml', 'application/vnd.google-earth.kmz' => 'kmz', 'application/vnd.grafeq' => 'gqf', 'application/vnd.groove-account' => 'gac', 'application/vnd.groove-help' => 'ghf', 'application/vnd.groove-identity-message' => 'gim', 'application/vnd.groove-injector' => 'grv', 'application/vnd.groove-tool-message' => 'gtm', 'application/vnd.groove-tool-template' => 'tpl', 'application/vnd.groove-vcard' => 'vcg', 'application/vnd.hal+xml' => 'hal', 'application/vnd.handheld-entertainment+xml' => 'zmm', 'application/vnd.hbci' => 'hbci', 'application/vnd.hhe.lesson-player' => 'les', 'application/vnd.hp-hpgl' => 'hpgl', 'application/vnd.hp-hpid' => 'hpid', 'application/vnd.hp-hps' => 'hps', 'application/vnd.hp-jlyt' => 'jlt', 'application/vnd.hp-pcl' => 'pcl', 'application/vnd.hp-pclxl' => 'pclxl', 'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx', 'application/vnd.ibm.minipay' => 'mpy', 'application/vnd.ibm.modcap' => 'afp', 'application/vnd.ibm.rights-management' => 'irm', 'application/vnd.ibm.secure-container' => 'sc', 'application/vnd.iccprofile' => 'icc', 'application/vnd.igloader' => 'igl', 'application/vnd.immervision-ivp' => 'ivp', 'application/vnd.immervision-ivu' => 'ivu', 'application/vnd.insors.igm' => 'igm', 'application/vnd.intercon.formnet' => 'xpw', 'application/vnd.intergeo' => 'i2g', 'application/vnd.intu.qbo' => 'qbo', 'application/vnd.intu.qfx' => 'qfx', 'application/vnd.ipunplugged.rcprofile' => 'rcprofile', 'application/vnd.irepository.package+xml' => 'irp', 'application/vnd.is-xpr' => 'xpr', 'application/vnd.isac.fcs' => 'fcs', 'application/vnd.jam' => 'jam', 'application/vnd.jcp.javame.midlet-rms' => 'rms', 'application/vnd.jisp' => 'jisp', 'application/vnd.joost.joda-archive' => 'joda', 'application/vnd.kahootz' => 'ktz', 'application/vnd.kde.karbon' => 'karbon', 'application/vnd.kde.kchart' => 'chrt', 'application/vnd.kde.kformula' => 'kfo', 'application/vnd.kde.kivio' => 'flw', 'application/vnd.kde.kontour' => 'kon', 'application/vnd.kde.kpresenter' => 'kpr', 'application/vnd.kde.kspread' => 'ksp', 'application/vnd.kde.kword' => 'kwd', 'application/vnd.kenameaapp' => 'htke', 'application/vnd.kidspiration' => 'kia', 'application/vnd.kinar' => 'kne', 'application/vnd.koan' => 'skp', 'application/vnd.kodak-descriptor' => 'sse', 'application/vnd.las.las+xml' => 'lasxml', 'application/vnd.llamagraphics.life-balance.desktop' => 'lbd', 'application/vnd.llamagraphics.life-balance.exchange+xml' => 'lbe', 'application/vnd.lotus-1-2-3' => '123', 'application/vnd.lotus-approach' => 'apr', 'application/vnd.lotus-freelance' => 'pre', 'application/vnd.lotus-notes' => 'nsf', 'application/vnd.lotus-organizer' => 'org', 'application/vnd.lotus-screencam' => 'scm', 'application/vnd.lotus-wordpro' => 'lwp', 'application/vnd.macports.portpkg' => 'portpkg', 'application/vnd.mcd' => 'mcd', 'application/vnd.medcalcdata' => 'mc1', 'application/vnd.mediastation.cdkey' => 'cdkey', 'application/vnd.mfer' => 'mwf', 'application/vnd.mfmp' => 'mfm', 'application/vnd.micrografx.flo' => 'flo', 'application/vnd.micrografx.igx' => 'igx', 'application/vnd.mif' => 'mif', 'application/vnd.mobius.daf' => 'daf', 'application/vnd.mobius.dis' => 'dis', 'application/vnd.mobius.mbk' => 'mbk', 'application/vnd.mobius.mqy' => 'mqy', 'application/vnd.mobius.msl' => 'msl', 'application/vnd.mobius.plc' => 'plc', 'application/vnd.mobius.txf' => 'txf', 'application/vnd.mophun.application' => 'mpn', 'application/vnd.mophun.certificate' => 'mpc', 'application/vnd.mozilla.xul+xml' => 'xul', 'application/vnd.ms-artgalry' => 'cil', 'application/vnd.ms-cab-compressed' => 'cab', 'application/vnd.ms-excel' => 'xls', 'application/vnd.ms-excel.addin.macroenabled.12' => 'xlam', 'application/vnd.ms-excel.sheet.binary.macroenabled.12' => 'xlsb', 'application/vnd.ms-excel.sheet.macroenabled.12' => 'xlsm', 'application/vnd.ms-excel.template.macroenabled.12' => 'xltm', 'application/vnd.ms-fontobject' => 'eot', 'application/vnd.ms-htmlhelp' => 'chm', 'application/vnd.ms-ims' => 'ims', 'application/vnd.ms-lrm' => 'lrm', 'application/vnd.ms-officetheme' => 'thmx', 'application/vnd.ms-pki.seccat' => 'cat', 'application/vnd.ms-pki.stl' => 'stl', 'application/vnd.ms-powerpoint' => 'ppt', 'application/vnd.ms-powerpoint.addin.macroenabled.12' => 'ppam', 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'pptm', 'application/vnd.ms-powerpoint.slide.macroenabled.12' => 'sldm', 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'ppsm', 'application/vnd.ms-powerpoint.template.macroenabled.12' => 'potm', 'application/vnd.ms-project' => 'mpp', 'application/vnd.ms-word.document.macroenabled.12' => 'docm', 'application/vnd.ms-word.template.macroenabled.12' => 'dotm', 'application/vnd.ms-works' => 'wps', 'application/vnd.ms-wpl' => 'wpl', 'application/vnd.ms-xpsdocument' => 'xps', 'application/vnd.mseq' => 'mseq', 'application/vnd.musician' => 'mus', 'application/vnd.muvee.style' => 'msty', 'application/vnd.mynfc' => 'taglet', 'application/vnd.neurolanguage.nlu' => 'nlu', 'application/vnd.nitf' => 'ntf', 'application/vnd.noblenet-directory' => 'nnd', 'application/vnd.noblenet-sealer' => 'nns', 'application/vnd.noblenet-web' => 'nnw', 'application/vnd.nokia.n-gage.data' => 'ngdat', 'application/vnd.nokia.n-gage.symbian.install' => 'n-gage', 'application/vnd.nokia.radio-preset' => 'rpst', 'application/vnd.nokia.radio-presets' => 'rpss', 'application/vnd.novadigm.edm' => 'edm', 'application/vnd.novadigm.edx' => 'edx', 'application/vnd.novadigm.ext' => 'ext', 'application/vnd.oasis.opendocument.chart' => 'odc', 'application/vnd.oasis.opendocument.chart-template' => 'otc', 'application/vnd.oasis.opendocument.database' => 'odb', 'application/vnd.oasis.opendocument.formula' => 'odf', 'application/vnd.oasis.opendocument.formula-template' => 'odft', 'application/vnd.oasis.opendocument.graphics' => 'odg', 'application/vnd.oasis.opendocument.graphics-template' => 'otg', 'application/vnd.oasis.opendocument.image' => 'odi', 'application/vnd.oasis.opendocument.image-template' => 'oti', 'application/vnd.oasis.opendocument.presentation' => 'odp', 'application/vnd.oasis.opendocument.presentation-template' => 'otp', 'application/vnd.oasis.opendocument.spreadsheet' => 'ods', 'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots', 'application/vnd.oasis.opendocument.text' => 'odt', 'application/vnd.oasis.opendocument.text-master' => 'odm', 'application/vnd.oasis.opendocument.text-template' => 'ott', 'application/vnd.oasis.opendocument.text-web' => 'oth', 'application/vnd.olpc-sugar' => 'xo', 'application/vnd.oma.dd2+xml' => 'dd2', 'application/vnd.openofficeorg.extension' => 'oxt', 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx', 'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx', 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx', 'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx', 'application/vnd.osgeo.mapguide.package' => 'mgp', 'application/vnd.osgi.dp' => 'dp', 'application/vnd.osgi.subsystem' => 'esa', 'application/vnd.palm' => 'pdb', 'application/vnd.pawaafile' => 'paw', 'application/vnd.pg.format' => 'str', 'application/vnd.pg.osasli' => 'ei6', 'application/vnd.picsel' => 'efif', 'application/vnd.pmi.widget' => 'wg', 'application/vnd.pocketlearn' => 'plf', 'application/vnd.powerbuilder6' => 'pbd', 'application/vnd.previewsystems.box' => 'box', 'application/vnd.proteus.magazine' => 'mgz', 'application/vnd.publishare-delta-tree' => 'qps', 'application/vnd.pvi.ptid1' => 'ptid', 'application/vnd.quark.quarkxpress' => 'qxd', 'application/vnd.realvnc.bed' => 'bed', 'application/vnd.recordare.musicxml' => 'mxl', 'application/vnd.recordare.musicxml+xml' => 'musicxml', 'application/vnd.rig.cryptonote' => 'cryptonote', 'application/vnd.rim.cod' => 'cod', 'application/vnd.rn-realmedia' => 'rm', 'application/vnd.rn-realmedia-vbr' => 'rmvb', 'application/vnd.route66.link66+xml' => 'link66', 'application/vnd.sailingtracker.track' => 'st', 'application/vnd.seemail' => 'see', 'application/vnd.sema' => 'sema', 'application/vnd.semd' => 'semd', 'application/vnd.semf' => 'semf', 'application/vnd.shana.informed.formdata' => 'ifm', 'application/vnd.shana.informed.formtemplate' => 'itp', 'application/vnd.shana.informed.interchange' => 'iif', 'application/vnd.shana.informed.package' => 'ipk', 'application/vnd.simtech-mindmapper' => 'twd', 'application/vnd.smaf' => 'mmf', 'application/vnd.smart.teacher' => 'teacher', 'application/vnd.solent.sdkm+xml' => 'sdkm', 'application/vnd.spotfire.dxp' => 'dxp', 'application/vnd.spotfire.sfs' => 'sfs', 'application/vnd.stardivision.calc' => 'sdc', 'application/vnd.stardivision.draw' => 'sda', 'application/vnd.stardivision.impress' => 'sdd', 'application/vnd.stardivision.math' => 'smf', 'application/vnd.stardivision.writer' => 'sdw', 'application/vnd.stardivision.writer-global' => 'sgl', 'application/vnd.stepmania.package' => 'smzip', 'application/vnd.stepmania.stepchart' => 'sm', 'application/vnd.sun.xml.calc' => 'sxc', 'application/vnd.sun.xml.calc.template' => 'stc', 'application/vnd.sun.xml.draw' => 'sxd', 'application/vnd.sun.xml.draw.template' => 'std', 'application/vnd.sun.xml.impress' => 'sxi', 'application/vnd.sun.xml.impress.template' => 'sti', 'application/vnd.sun.xml.math' => 'sxm', 'application/vnd.sun.xml.writer' => 'sxw', 'application/vnd.sun.xml.writer.global' => 'sxg', 'application/vnd.sun.xml.writer.template' => 'stw', 'application/vnd.sus-calendar' => 'sus', 'application/vnd.svd' => 'svd', 'application/vnd.symbian.install' => 'sis', 'application/vnd.syncml+xml' => 'xsm', 'application/vnd.syncml.dm+wbxml' => 'bdm', 'application/vnd.syncml.dm+xml' => 'xdm', 'application/vnd.tao.intent-module-archive' => 'tao', 'application/vnd.tcpdump.pcap' => 'pcap', 'application/vnd.tmobile-livetv' => 'tmo', 'application/vnd.trid.tpt' => 'tpt', 'application/vnd.triscape.mxs' => 'mxs', 'application/vnd.trueapp' => 'tra', 'application/vnd.ufdl' => 'ufd', 'application/vnd.uiq.theme' => 'utz', 'application/vnd.umajin' => 'umj', 'application/vnd.unity' => 'unityweb', 'application/vnd.uoml+xml' => 'uoml', 'application/vnd.vcx' => 'vcx', 'application/vnd.visio' => 'vsd', 'application/vnd.visionary' => 'vis', 'application/vnd.vsf' => 'vsf', 'application/vnd.wap.wbxml' => 'wbxml', 'application/vnd.wap.wmlc' => 'wmlc', 'application/vnd.wap.wmlscriptc' => 'wmlsc', 'application/vnd.webturbo' => 'wtb', 'application/vnd.wolfram.player' => 'nbp', 'application/vnd.wordperfect' => 'wpd', 'application/vnd.wqd' => 'wqd', 'application/vnd.wt.stf' => 'stf', 'application/vnd.xara' => 'xar', 'application/vnd.xfdl' => 'xfdl', 'application/vnd.yamaha.hv-dic' => 'hvd', 'application/vnd.yamaha.hv-script' => 'hvs', 'application/vnd.yamaha.hv-voice' => 'hvp', 'application/vnd.yamaha.openscoreformat' => 'osf', 'application/vnd.yamaha.openscoreformat.osfpvg+xml' => 'osfpvg', 'application/vnd.yamaha.smaf-audio' => 'saf', 'application/vnd.yamaha.smaf-phrase' => 'spf', 'application/vnd.yellowriver-custom-menu' => 'cmp', 'application/vnd.zul' => 'zir', 'application/vnd.zzazz.deck+xml' => 'zaz', 'application/voicexml+xml' => 'vxml', 'application/widget' => 'wgt', 'application/winhlp' => 'hlp', 'application/wsdl+xml' => 'wsdl', 'application/wspolicy+xml' => 'wspolicy', 'application/x-7z-compressed' => '7z', 'application/x-abiword' => 'abw', 'application/x-ace-compressed' => 'ace', 'application/x-apple-diskimage' => 'dmg', 'application/x-authorware-bin' => 'aab', 'application/x-authorware-map' => 'aam', 'application/x-authorware-seg' => 'aas', 'application/x-bcpio' => 'bcpio', 'application/x-bittorrent' => 'torrent', 'application/x-blorb' => 'blb', 'application/x-bzip' => 'bz', 'application/x-bzip2' => 'bz2', 'application/x-cbr' => 'cbr', 'application/x-cdlink' => 'vcd', 'application/x-cfs-compressed' => 'cfs', 'application/x-chat' => 'chat', 'application/x-chess-pgn' => 'pgn', 'application/x-conference' => 'nsc', 'application/x-cpio' => 'cpio', 'application/x-csh' => 'csh', 'application/x-debian-package' => 'deb', 'application/x-dgc-compressed' => 'dgc', 'application/x-director' => 'dir', 'application/x-doom' => 'wad', 'application/x-dtbncx+xml' => 'ncx', 'application/x-dtbook+xml' => 'dtb', 'application/x-dtbresource+xml' => 'res', 'application/x-dvi' => 'dvi', 'application/x-envoy' => 'evy', 'application/x-eva' => 'eva', 'application/x-font-bdf' => 'bdf', 'application/x-font-ghostscript' => 'gsf', 'application/x-font-linux-psf' => 'psf', 'application/x-font-otf' => 'otf', 'application/x-font-pcf' => 'pcf', 'application/x-font-snf' => 'snf', 'application/x-font-ttf' => 'ttf', 'application/x-font-type1' => 'pfa', 'application/x-font-woff' => 'woff', 'application/x-freearc' => 'arc', 'application/x-futuresplash' => 'spl', 'application/x-gca-compressed' => 'gca', 'application/x-glulx' => 'ulx', 'application/x-gnumeric' => 'gnumeric', 'application/x-gramps-xml' => 'gramps', 'application/x-gtar' => 'gtar', 'application/x-hdf' => 'hdf', 'application/x-install-instructions' => 'install', 'application/x-iso9660-image' => 'iso', 'application/x-java-jnlp-file' => 'jnlp', 'application/x-latex' => 'latex', 'application/x-lzh-compressed' => 'lzh', 'application/x-mie' => 'mie', 'application/x-mobipocket-ebook' => 'prc', 'application/x-ms-application' => 'application', 'application/x-ms-shortcut' => 'lnk', 'application/x-ms-wmd' => 'wmd', 'application/x-ms-wmz' => 'wmz', 'application/x-ms-xbap' => 'xbap', 'application/x-msaccess' => 'mdb', 'application/x-msbinder' => 'obd', 'application/x-mscardfile' => 'crd', 'application/x-msclip' => 'clp', 'application/x-msdownload' => 'exe', 'application/x-msmediaview' => 'mvb', 'application/x-msmetafile' => 'wmf', 'application/x-msmoney' => 'mny', 'application/x-mspublisher' => 'pub', 'application/x-msschedule' => 'scd', 'application/x-msterminal' => 'trm', 'application/x-mswrite' => 'wri', 'application/x-netcdf' => 'nc', 'application/x-nzb' => 'nzb', 'application/x-pkcs12' => 'p12', 'application/x-pkcs7-certificates' => 'p7b', 'application/x-pkcs7-certreqresp' => 'p7r', 'application/x-rar-compressed' => 'rar', 'application/x-rar' => 'rar', 'application/x-research-info-systems' => 'ris', 'application/x-sh' => 'sh', 'application/x-shar' => 'shar', 'application/x-shockwave-flash' => 'swf', 'application/x-silverlight-app' => 'xap', 'application/x-sql' => 'sql', 'application/x-stuffit' => 'sit', 'application/x-stuffitx' => 'sitx', 'application/x-subrip' => 'srt', 'application/x-sv4cpio' => 'sv4cpio', 'application/x-sv4crc' => 'sv4crc', 'application/x-t3vm-image' => 't3', 'application/x-tads' => 'gam', 'application/x-tar' => 'tar', 'application/x-tcl' => 'tcl', 'application/x-tex' => 'tex', 'application/x-tex-tfm' => 'tfm', 'application/x-texinfo' => 'texinfo', 'application/x-tgif' => 'obj', 'application/x-ustar' => 'ustar', 'application/x-wais-source' => 'src', 'application/x-x509-ca-cert' => 'der', 'application/x-xfig' => 'fig', 'application/x-xliff+xml' => 'xlf', 'application/x-xpinstall' => 'xpi', 'application/x-xz' => 'xz', 'application/x-zmachine' => 'z1', 'application/xaml+xml' => 'xaml', 'application/xcap-diff+xml' => 'xdf', 'application/xenc+xml' => 'xenc', 'application/xhtml+xml' => 'xhtml', 'application/xml' => 'xml', 'application/xml-dtd' => 'dtd', 'application/xop+xml' => 'xop', 'application/xproc+xml' => 'xpl', 'application/xslt+xml' => 'xslt', 'application/xspf+xml' => 'xspf', 'application/xv+xml' => 'mxml', 'application/yang' => 'yang', 'application/yin+xml' => 'yin', 'application/zip' => 'zip', 'audio/adpcm' => 'adp', 'audio/basic' => 'au', 'audio/midi' => 'mid', 'audio/mp4' => 'mp4a', 'audio/mpeg' => 'mpga', 'audio/ogg' => 'oga', 'audio/s3m' => 's3m', 'audio/silk' => 'sil', 'audio/vnd.dece.audio' => 'uva', 'audio/vnd.digital-winds' => 'eol', 'audio/vnd.dra' => 'dra', 'audio/vnd.dts' => 'dts', 'audio/vnd.dts.hd' => 'dtshd', 'audio/vnd.lucent.voice' => 'lvp', 'audio/vnd.ms-playready.media.pya' => 'pya', 'audio/vnd.nuera.ecelp4800' => 'ecelp4800', 'audio/vnd.nuera.ecelp7470' => 'ecelp7470', 'audio/vnd.nuera.ecelp9600' => 'ecelp9600', 'audio/vnd.rip' => 'rip', 'audio/webm' => 'weba', 'audio/x-aac' => 'aac', 'audio/x-aiff' => 'aif', 'audio/x-caf' => 'caf', 'audio/x-flac' => 'flac', 'audio/x-matroska' => 'mka', 'audio/x-mpegurl' => 'm3u', 'audio/x-ms-wax' => 'wax', 'audio/x-ms-wma' => 'wma', 'audio/x-pn-realaudio' => 'ram', 'audio/x-pn-realaudio-plugin' => 'rmp', 'audio/x-wav' => 'wav', 'audio/xm' => 'xm', 'chemical/x-cdx' => 'cdx', 'chemical/x-cif' => 'cif', 'chemical/x-cmdf' => 'cmdf', 'chemical/x-cml' => 'cml', 'chemical/x-csml' => 'csml', 'chemical/x-xyz' => 'xyz', 'image/bmp' => 'bmp', 'image/cgm' => 'cgm', 'image/g3fax' => 'g3', 'image/gif' => 'gif', 'image/ief' => 'ief', 'image/jpeg' => 'jpeg', 'image/ktx' => 'ktx', 'image/png' => 'png', 'image/prs.btif' => 'btif', 'image/sgi' => 'sgi', 'image/svg+xml' => 'svg', 'image/tiff' => 'tiff', 'image/vnd.adobe.photoshop' => 'psd', 'image/vnd.dece.graphic' => 'uvi', 'image/vnd.dvb.subtitle' => 'sub', 'image/vnd.djvu' => 'djvu', 'image/vnd.dwg' => 'dwg', 'image/vnd.dxf' => 'dxf', 'image/vnd.fastbidsheet' => 'fbs', 'image/vnd.fpx' => 'fpx', 'image/vnd.fst' => 'fst', 'image/vnd.fujixerox.edmics-mmr' => 'mmr', 'image/vnd.fujixerox.edmics-rlc' => 'rlc', 'image/vnd.ms-modi' => 'mdi', 'image/vnd.ms-photo' => 'wdp', 'image/vnd.net-fpx' => 'npx', 'image/vnd.wap.wbmp' => 'wbmp', 'image/vnd.xiff' => 'xif', 'image/webp' => 'webp', 'image/x-3ds' => '3ds', 'image/x-cmu-raster' => 'ras', 'image/x-cmx' => 'cmx', 'image/x-freehand' => 'fh', 'image/x-icon' => 'ico', 'image/x-mrsid-image' => 'sid', 'image/x-pcx' => 'pcx', 'image/x-pict' => 'pic', 'image/x-portable-anymap' => 'pnm', 'image/x-portable-bitmap' => 'pbm', 'image/x-portable-graymap' => 'pgm', 'image/x-portable-pixmap' => 'ppm', 'image/x-rgb' => 'rgb', 'image/x-tga' => 'tga', 'image/x-xbitmap' => 'xbm', 'image/x-xpixmap' => 'xpm', 'image/x-xwindowdump' => 'xwd', 'message/rfc822' => 'eml', 'model/iges' => 'igs', 'model/mesh' => 'msh', 'model/vnd.collada+xml' => 'dae', 'model/vnd.dwf' => 'dwf', 'model/vnd.gdl' => 'gdl', 'model/vnd.gtw' => 'gtw', 'model/vnd.mts' => 'mts', 'model/vnd.vtu' => 'vtu', 'model/vrml' => 'wrl', 'model/x3d+binary' => 'x3db', 'model/x3d+vrml' => 'x3dv', 'model/x3d+xml' => 'x3d', 'text/cache-manifest' => 'appcache', 'text/calendar' => 'ics', 'text/css' => 'css', 'text/csv' => 'csv', 'text/html' => 'html', 'text/n3' => 'n3', 'text/plain' => 'txt', 'text/prs.lines.tag' => 'dsc', 'text/richtext' => 'rtx', 'text/sgml' => 'sgml', 'text/tab-separated-values' => 'tsv', 'text/troff' => 't', 'text/turtle' => 'ttl', 'text/uri-list' => 'uri', 'text/vcard' => 'vcard', 'text/vnd.curl' => 'curl', 'text/vnd.curl.dcurl' => 'dcurl', 'text/vnd.curl.scurl' => 'scurl', 'text/vnd.curl.mcurl' => 'mcurl', 'text/vnd.dvb.subtitle' => 'sub', 'text/vnd.fly' => 'fly', 'text/vnd.fmi.flexstor' => 'flx', 'text/vnd.graphviz' => 'gv', 'text/vnd.in3d.3dml' => '3dml', 'text/vnd.in3d.spot' => 'spot', 'text/vnd.sun.j2me.app-descriptor' => 'jad', 'text/vnd.wap.wml' => 'wml', 'text/vnd.wap.wmlscript' => 'wmls', 'text/x-asm' => 's', 'text/x-c' => 'c', 'text/x-fortran' => 'f', 'text/x-pascal' => 'p', 'text/x-java-source' => 'java', 'text/x-opml' => 'opml', 'text/x-nfo' => 'nfo', 'text/x-setext' => 'etx', 'text/x-sfv' => 'sfv', 'text/x-uuencode' => 'uu', 'text/x-vcalendar' => 'vcs', 'text/x-vcard' => 'vcf', 'video/3gpp' => '3gp', 'video/3gpp2' => '3g2', 'video/h261' => 'h261', 'video/h263' => 'h263', 'video/h264' => 'h264', 'video/jpeg' => 'jpgv', 'video/jpm' => 'jpm', 'video/mj2' => 'mj2', 'video/mp4' => 'mp4', 'video/mpeg' => 'mpeg', 'video/ogg' => 'ogv', 'video/quicktime' => 'qt', 'video/vnd.dece.hd' => 'uvh', 'video/vnd.dece.mobile' => 'uvm', 'video/vnd.dece.pd' => 'uvp', 'video/vnd.dece.sd' => 'uvs', 'video/vnd.dece.video' => 'uvv', 'video/vnd.dvb.file' => 'dvb', 'video/vnd.fvt' => 'fvt', 'video/vnd.mpegurl' => 'mxu', 'video/vnd.ms-playready.media.pyv' => 'pyv', 'video/vnd.uvvu.mp4' => 'uvu', 'video/vnd.vivo' => 'viv', 'video/webm' => 'webm', 'video/x-f4v' => 'f4v', 'video/x-fli' => 'fli', 'video/x-flv' => 'flv', 'video/x-m4v' => 'm4v', 'video/x-matroska' => 'mkv', 'video/x-mng' => 'mng', 'video/x-ms-asf' => 'asf', 'video/x-ms-vob' => 'vob', 'video/x-ms-wm' => 'wm', 'video/x-ms-wmv' => 'wmv', 'video/x-ms-wmx' => 'wmx', 'video/x-ms-wvx' => 'wvx', 'video/x-msvideo' => 'avi', 'video/x-sgi-movie' => 'movie', 'video/x-smv' => 'smv', 'x-conference/x-cooltalk' => 'ice', ); /** * {@inheritdoc} */ public function guess($mimeType) { return isset($this->defaultExtensions[$mimeType]) ? $this->defaultExtensions[$mimeType] : null; } } PK]5p18HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; /** * Guesses the mime type using the PECL extension FileInfo. * * @author Bernhard Schussek */ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface { private $magicFile; /** * Constructor. * * @param string $magicFile A magic file to use with the finfo instance * * @link http://www.php.net/manual/en/function.finfo-open.php */ public function __construct($magicFile = null) { $this->magicFile = $magicFile; } /** * Returns whether this guesser is supported on the current OS/PHP setup * * @return Boolean */ public static function isSupported() { return function_exists('finfo_open'); } /** * {@inheritdoc} */ public function guess($path) { if (!is_file($path)) { throw new FileNotFoundException($path); } if (!is_readable($path)) { throw new AccessDeniedException($path); } if (!self::isSupported()) { return null; } if (!$finfo = new \finfo(FILEINFO_MIME_TYPE, $this->magicFile)) { return null; } return $finfo->file($path); } } PK]q x:HttpFoundation/File/MimeType/ExtensionGuesserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; /** * Guesses the file extension corresponding to a given mime type */ interface ExtensionGuesserInterface { /** * Makes a best guess for a file extension, given a mime type * * @param string $mimeType The mime type * @return string The guessed extension or NULL, if none could be guessed */ public function guess($mimeType); } PK]2 k 1HttpFoundation/File/MimeType/ExtensionGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; /** * A singleton mime type to file extension guesser. * * A default guesser is provided. * You can register custom guessers by calling the register() * method on the singleton instance: * * $guesser = ExtensionGuesser::getInstance(); * $guesser->register(new MyCustomExtensionGuesser()); * * The last registered guesser is preferred over previously registered ones. */ class ExtensionGuesser implements ExtensionGuesserInterface { /** * The singleton instance * * @var ExtensionGuesser */ private static $instance = null; /** * All registered ExtensionGuesserInterface instances * * @var array */ protected $guessers = array(); /** * Returns the singleton instance * * @return ExtensionGuesser */ public static function getInstance() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; } /** * Registers all natively provided extension guessers */ private function __construct() { $this->register(new MimeTypeExtensionGuesser()); } /** * Registers a new extension guesser * * When guessing, this guesser is preferred over previously registered ones. * * @param ExtensionGuesserInterface $guesser */ public function register(ExtensionGuesserInterface $guesser) { array_unshift($this->guessers, $guesser); } /** * Tries to guess the extension * * The mime type is passed to each registered mime type guesser in reverse order * of their registration (last registered is queried first). Once a guesser * returns a value that is not NULL, this method terminates and returns the * value. * * @param string $mimeType The mime type * * @return string The guessed extension or NULL, if none could be guessed */ public function guess($mimeType) { foreach ($this->guessers as $guesser) { if (null !== $extension = $guesser->guess($mimeType)) { return $extension; } } } } PK]J:HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; /** * Guesses the mime type with the binary "file" (only available on *nix) * * @author Bernhard Schussek */ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface { private $cmd; /** * Constructor. * * The $cmd pattern must contain a "%s" string that will be replaced * with the file name to guess. * * The command output must start with the mime type of the file. * * @param string $cmd The command to run to get the mime type of a file */ public function __construct($cmd = 'file -b --mime %s 2>/dev/null') { $this->cmd = $cmd; } /** * Returns whether this guesser is supported on the current OS * * @return Boolean */ public static function isSupported() { return !defined('PHP_WINDOWS_VERSION_BUILD') && function_exists('passthru') && function_exists('escapeshellarg'); } /** * {@inheritdoc} */ public function guess($path) { if (!is_file($path)) { throw new FileNotFoundException($path); } if (!is_readable($path)) { throw new AccessDeniedException($path); } if (!self::isSupported()) { return null; } ob_start(); // need to use --mime instead of -i. see #6641 passthru(sprintf($this->cmd, escapeshellarg($path)), $return); if ($return > 0) { ob_end_clean(); return null; } $type = trim(ob_get_clean()); if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) { // it's not a type, but an error message return null; } return $match[1]; } } PK]1e7HttpFoundation/File/Exception/AccessDeniedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when the access on a file was denied. * * @author Bernhard Schussek */ class AccessDeniedException extends FileException { /** * Constructor. * * @param string $path The path to the accessed file */ public function __construct($path) { parent::__construct(sprintf('The file %s could not be accessed', $path)); } } PK]gr1HttpFoundation/File/Exception/UploadException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an error occurred during file upload * * @author Bernhard Schussek */ class UploadException extends FileException { } PK]s-7HttpFoundation/File/Exception/FileNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when a file was not found * * @author Bernhard Schussek */ class FileNotFoundException extends FileException { /** * Constructor. * * @param string $path The path to the file that was not found */ public function __construct($path) { parent::__construct(sprintf('The file "%s" does not exist', $path)); } } PK]S==9HttpFoundation/File/Exception/UnexpectedTypeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; class UnexpectedTypeException extends FileException { public function __construct($value, $expectedType) { parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, is_object($value) ? get_class($value) : gettype($value))); } } PK]o/HttpFoundation/File/Exception/FileException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an error occurred in the component File * * @author Bernhard Schussek */ class FileException extends \RuntimeException { } PK])HttpFoundation/File/File.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File; use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser; /** * A file in the file system. * * @author Bernhard Schussek * * @api */ class File extends \SplFileInfo { /** * Constructs a new file from the given path. * * @param string $path The path to the file * @param Boolean $checkPath Whether to check the path or not * * @throws FileNotFoundException If the given path is not a file * * @api */ public function __construct($path, $checkPath = true) { if ($checkPath && !is_file($path)) { throw new FileNotFoundException($path); } parent::__construct($path); } /** * Returns the extension based on the mime type. * * If the mime type is unknown, returns null. * * This method uses the mime type as guessed by getMimeType() * to guess the file extension. * * @return string|null The guessed extension or null if it cannot be guessed * * @api * * @see ExtensionGuesser * @see getMimeType() */ public function guessExtension() { $type = $this->getMimeType(); $guesser = ExtensionGuesser::getInstance(); return $guesser->guess($type); } /** * Returns the mime type of the file. * * The mime type is guessed using a MimeTypeGuesser instance, which uses finfo(), * mime_content_type() and the system binary "file" (in this order), depending on * which of those are available. * * @return string|null The guessed mime type (i.e. "application/pdf") * * @see MimeTypeGuesser * * @api */ public function getMimeType() { $guesser = MimeTypeGuesser::getInstance(); return $guesser->guess($this->getPathname()); } /** * Returns the extension of the file. * * \SplFileInfo::getExtension() is not available before PHP 5.3.6 * * @return string The extension * * @api */ public function getExtension() { return pathinfo($this->getBasename(), PATHINFO_EXTENSION); } /** * Moves the file to a new location. * * @param string $directory The destination folder * @param string $name The new file name * * @return File A File object representing the new file * * @throws FileException if the target file could not be created * * @api */ public function move($directory, $name = null) { $target = $this->getTargetFile($directory, $name); if (!@rename($this->getPathname(), $target)) { $error = error_get_last(); throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message']))); } @chmod($target, 0666 & ~umask()); return $target; } protected function getTargetFile($directory, $name = null) { if (!is_dir($directory)) { if (false === @mkdir($directory, 0777, true)) { throw new FileException(sprintf('Unable to create the "%s" directory', $directory)); } } elseif (!is_writable($directory)) { throw new FileException(sprintf('Unable to write in the "%s" directory', $directory)); } $target = rtrim($directory, '/\\').DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name)); return new File($target, false); } /** * Returns locale independent base name of the given path. * * @param string $name The new file name * * @return string containing */ protected function getName($name) { $originalName = str_replace('\\', '/', $name); $pos = strrpos($originalName, '/'); $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1); return $originalName; } } PK]8{?!HttpFoundation/RequestMatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * RequestMatcher compares a pre-defined set of checks against a Request instance. * * @author Fabien Potencier * * @api */ class RequestMatcher implements RequestMatcherInterface { /** * @var string */ private $path; /** * @var string */ private $host; /** * @var array */ private $methods = array(); /** * @var string */ private $ips = array(); /** * @var array */ private $attributes = array(); /** * @param string|null $path * @param string|null $host * @param string|string[]|null $methods * @param string|string[]|null $ips * @param array $attributes */ public function __construct($path = null, $host = null, $methods = null, $ips = null, array $attributes = array()) { $this->matchPath($path); $this->matchHost($host); $this->matchMethod($methods); $this->matchIps($ips); foreach ($attributes as $k => $v) { $this->matchAttribute($k, $v); } } /** * Adds a check for the URL host name. * * @param string $regexp A Regexp */ public function matchHost($regexp) { $this->host = $regexp; } /** * Adds a check for the URL path info. * * @param string $regexp A Regexp */ public function matchPath($regexp) { $this->path = $regexp; } /** * Adds a check for the client IP. * * @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 */ public function matchIp($ip) { $this->matchIps($ip); } /** * Adds a check for the client IP. * * @param string|string[] $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 */ public function matchIps($ips) { $this->ips = (array) $ips; } /** * Adds a check for the HTTP method. * * @param string|string[]|null $method An HTTP method or an array of HTTP methods */ public function matchMethod($method) { $this->methods = array_map('strtoupper', (array) $method); } /** * Adds a check for request attribute. * * @param string $key The request attribute name * @param string $regexp A Regexp */ public function matchAttribute($key, $regexp) { $this->attributes[$key] = $regexp; } /** * {@inheritdoc} * * @api */ public function matches(Request $request) { if ($this->methods && !in_array($request->getMethod(), $this->methods)) { return false; } foreach ($this->attributes as $key => $pattern) { if (!preg_match('{'.$pattern.'}', $request->attributes->get($key))) { return false; } } if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getPathInfo()))) { return false; } if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getHost())) { return false; } if (IpUtils::checkIp($request->getClientIp(), $this->ips)) { return true; } // Note to future implementors: add additional checks above the // foreach above or else your check might not be run! return count($this->ips) === 0; } } PK]pߋߋHttpFoundation/Response.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Response represents an HTTP response. * * @author Fabien Potencier * * @api */ class Response { const HTTP_CONTINUE = 100; const HTTP_SWITCHING_PROTOCOLS = 101; const HTTP_PROCESSING = 102; // RFC2518 const HTTP_OK = 200; const HTTP_CREATED = 201; const HTTP_ACCEPTED = 202; const HTTP_NON_AUTHORITATIVE_INFORMATION = 203; const HTTP_NO_CONTENT = 204; const HTTP_RESET_CONTENT = 205; const HTTP_PARTIAL_CONTENT = 206; const HTTP_MULTI_STATUS = 207; // RFC4918 const HTTP_ALREADY_REPORTED = 208; // RFC5842 const HTTP_IM_USED = 226; // RFC3229 const HTTP_MULTIPLE_CHOICES = 300; const HTTP_MOVED_PERMANENTLY = 301; const HTTP_FOUND = 302; const HTTP_SEE_OTHER = 303; const HTTP_NOT_MODIFIED = 304; const HTTP_USE_PROXY = 305; const HTTP_RESERVED = 306; const HTTP_TEMPORARY_REDIRECT = 307; const HTTP_PERMANENTLY_REDIRECT = 308; // RFC-reschke-http-status-308-07 const HTTP_BAD_REQUEST = 400; const HTTP_UNAUTHORIZED = 401; const HTTP_PAYMENT_REQUIRED = 402; const HTTP_FORBIDDEN = 403; const HTTP_NOT_FOUND = 404; const HTTP_METHOD_NOT_ALLOWED = 405; const HTTP_NOT_ACCEPTABLE = 406; const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; const HTTP_REQUEST_TIMEOUT = 408; const HTTP_CONFLICT = 409; const HTTP_GONE = 410; const HTTP_LENGTH_REQUIRED = 411; const HTTP_PRECONDITION_FAILED = 412; const HTTP_REQUEST_ENTITY_TOO_LARGE = 413; const HTTP_REQUEST_URI_TOO_LONG = 414; const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; const HTTP_EXPECTATION_FAILED = 417; const HTTP_I_AM_A_TEAPOT = 418; // RFC2324 const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918 const HTTP_LOCKED = 423; // RFC4918 const HTTP_FAILED_DEPENDENCY = 424; // RFC4918 const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425; // RFC2817 const HTTP_UPGRADE_REQUIRED = 426; // RFC2817 const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585 const HTTP_INTERNAL_SERVER_ERROR = 500; const HTTP_NOT_IMPLEMENTED = 501; const HTTP_BAD_GATEWAY = 502; const HTTP_SERVICE_UNAVAILABLE = 503; const HTTP_GATEWAY_TIMEOUT = 504; const HTTP_VERSION_NOT_SUPPORTED = 505; const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295 const HTTP_INSUFFICIENT_STORAGE = 507; // RFC4918 const HTTP_LOOP_DETECTED = 508; // RFC5842 const HTTP_NOT_EXTENDED = 510; // RFC2774 const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585 /** * @var \Symfony\Component\HttpFoundation\ResponseHeaderBag */ public $headers; /** * @var string */ protected $content; /** * @var string */ protected $version; /** * @var integer */ protected $statusCode; /** * @var string */ protected $statusText; /** * @var string */ protected $charset; /** * Status codes translation table. * * The list of codes is complete according to the * {@link http://www.iana.org/assignments/http-status-codes/ Hypertext Transfer Protocol (HTTP) Status Code Registry} * (last updated 2012-02-13). * * Unless otherwise noted, the status code is defined in RFC2616. * * @var array */ public static $statusTexts = array( 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', // RFC2518 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', // RFC4918 208 => 'Already Reported', // RFC5842 226 => 'IM Used', // RFC3229 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Reserved', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', // RFC-reschke-http-status-308-07 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', // RFC2324 422 => 'Unprocessable Entity', // RFC4918 423 => 'Locked', // RFC4918 424 => 'Failed Dependency', // RFC4918 425 => 'Reserved for WebDAV advanced collections expired proposal', // RFC2817 426 => 'Upgrade Required', // RFC2817 428 => 'Precondition Required', // RFC6585 429 => 'Too Many Requests', // RFC6585 431 => 'Request Header Fields Too Large', // RFC6585 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates (Experimental)', // RFC2295 507 => 'Insufficient Storage', // RFC4918 508 => 'Loop Detected', // RFC5842 510 => 'Not Extended', // RFC2774 511 => 'Network Authentication Required', // RFC6585 ); /** * Constructor. * * @param mixed $content The response content, see setContent() * @param integer $status The response status code * @param array $headers An array of response headers * * @throws \InvalidArgumentException When the HTTP status code is not valid * * @api */ public function __construct($content = '', $status = 200, $headers = array()) { $this->headers = new ResponseHeaderBag($headers); $this->setContent($content); $this->setStatusCode($status); $this->setProtocolVersion('1.0'); if (!$this->headers->has('Date')) { $this->setDate(new \DateTime(null, new \DateTimeZone('UTC'))); } } /** * Factory method for chainability * * Example: * * return Response::create($body, 200) * ->setSharedMaxAge(300); * * @param mixed $content The response content, see setContent() * @param integer $status The response status code * @param array $headers An array of response headers * * @return Response */ public static function create($content = '', $status = 200, $headers = array()) { return new static($content, $status, $headers); } /** * Returns the Response as an HTTP string. * * The string representation of the Response is the same as the * one that will be sent to the client only if the prepare() method * has been called before. * * @return string The Response as an HTTP string * * @see prepare() */ public function __toString() { return sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n". $this->headers."\r\n". $this->getContent(); } /** * Clones the current Response instance. */ public function __clone() { $this->headers = clone $this->headers; } /** * Prepares the Response before it is sent to the client. * * This method tweaks the Response to ensure that it is * compliant with RFC 2616. Most of the changes are based on * the Request that is "associated" with this Response. * * @param Request $request A Request instance * * @return Response The current response. */ public function prepare(Request $request) { $headers = $this->headers; if ($this->isInformational() || in_array($this->statusCode, array(204, 304))) { $this->setContent(null); } // Content-type based on the Request if (!$headers->has('Content-Type')) { $format = $request->getRequestFormat(); if (null !== $format && $mimeType = $request->getMimeType($format)) { $headers->set('Content-Type', $mimeType); } } // Fix Content-Type $charset = $this->charset ?: 'UTF-8'; if (!$headers->has('Content-Type')) { $headers->set('Content-Type', 'text/html; charset='.$charset); } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) { // add the charset $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset); } // Fix Content-Length if ($headers->has('Transfer-Encoding')) { $headers->remove('Content-Length'); } if ($request->isMethod('HEAD')) { // cf. RFC2616 14.13 $length = $headers->get('Content-Length'); $this->setContent(null); if ($length) { $headers->set('Content-Length', $length); } } // Fix protocol if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { $this->setProtocolVersion('1.1'); } // Check if we need to send extra expire info headers if ('1.0' == $this->getProtocolVersion() && 'no-cache' == $this->headers->get('Cache-Control')) { $this->headers->set('pragma', 'no-cache'); $this->headers->set('expires', -1); } $this->ensureIEOverSSLCompatibility($request); return $this; } /** * Sends HTTP headers. * * @return Response */ public function sendHeaders() { // headers have already been sent by the developer if (headers_sent()) { return $this; } // status header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); // headers foreach ($this->headers->allPreserveCase() as $name => $values) { foreach ($values as $value) { header($name.': '.$value, false, $this->statusCode); } } // cookies foreach ($this->headers->getCookies() as $cookie) { setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); } return $this; } /** * Sends content for the current web response. * * @return Response */ public function sendContent() { echo $this->content; return $this; } /** * Sends HTTP headers and content. * * @return Response * * @api */ public function send() { $this->sendHeaders(); $this->sendContent(); if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } elseif ('cli' !== PHP_SAPI) { // ob_get_level() never returns 0 on some Windows configurations, so if // the level is the same two times in a row, the loop should be stopped. $previous = null; $obStatus = ob_get_status(1); while (($level = ob_get_level()) > 0 && $level !== $previous) { $previous = $level; if ($obStatus[$level - 1]) { if (version_compare(PHP_VERSION, '5.4', '>=')) { if (isset($obStatus[$level - 1]['flags']) && ($obStatus[$level - 1]['flags'] & PHP_OUTPUT_HANDLER_REMOVABLE)) { ob_end_flush(); } } else { if (isset($obStatus[$level - 1]['del']) && $obStatus[$level - 1]['del']) { ob_end_flush(); } } } } flush(); } return $this; } /** * Sets the response content. * * Valid types are strings, numbers, null, and objects that implement a __toString() method. * * @param mixed $content Content that can be cast to string * * @return Response * * @throws \UnexpectedValueException * * @api */ public function setContent($content) { if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable(array($content, '__toString'))) { throw new \UnexpectedValueException(sprintf('The Response content must be a string or object implementing __toString(), "%s" given.', gettype($content))); } $this->content = (string) $content; return $this; } /** * Gets the current response content. * * @return string Content * * @api */ public function getContent() { return $this->content; } /** * Sets the HTTP protocol version (1.0 or 1.1). * * @param string $version The HTTP protocol version * * @return Response * * @api */ public function setProtocolVersion($version) { $this->version = $version; return $this; } /** * Gets the HTTP protocol version. * * @return string The HTTP protocol version * * @api */ public function getProtocolVersion() { return $this->version; } /** * Sets the response status code. * * @param integer $code HTTP status code * @param mixed $text HTTP status text * * If the status text is null it will be automatically populated for the known * status codes and left empty otherwise. * * @return Response * * @throws \InvalidArgumentException When the HTTP status code is not valid * * @api */ public function setStatusCode($code, $text = null) { $this->statusCode = $code = (int) $code; if ($this->isInvalid()) { throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code)); } if (null === $text) { $this->statusText = isset(self::$statusTexts[$code]) ? self::$statusTexts[$code] : ''; return $this; } if (false === $text) { $this->statusText = ''; return $this; } $this->statusText = $text; return $this; } /** * Retrieves the status code for the current web response. * * @return integer Status code * * @api */ public function getStatusCode() { return $this->statusCode; } /** * Sets the response charset. * * @param string $charset Character set * * @return Response * * @api */ public function setCharset($charset) { $this->charset = $charset; return $this; } /** * Retrieves the response charset. * * @return string Character set * * @api */ public function getCharset() { return $this->charset; } /** * Returns true if the response is worth caching under any circumstance. * * Responses marked "private" with an explicit Cache-Control directive are * considered uncacheable. * * Responses with neither a freshness lifetime (Expires, max-age) nor cache * validator (Last-Modified, ETag) are considered uncacheable. * * @return Boolean true if the response is worth caching, false otherwise * * @api */ public function isCacheable() { if (!in_array($this->statusCode, array(200, 203, 300, 301, 302, 404, 410))) { return false; } if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) { return false; } return $this->isValidateable() || $this->isFresh(); } /** * Returns true if the response is "fresh". * * Fresh responses may be served from cache without any interaction with the * origin. A response is considered fresh when it includes a Cache-Control/max-age * indicator or Expires header and the calculated age is less than the freshness lifetime. * * @return Boolean true if the response is fresh, false otherwise * * @api */ public function isFresh() { return $this->getTtl() > 0; } /** * Returns true if the response includes headers that can be used to validate * the response with the origin server using a conditional GET request. * * @return Boolean true if the response is validateable, false otherwise * * @api */ public function isValidateable() { return $this->headers->has('Last-Modified') || $this->headers->has('ETag'); } /** * Marks the response as "private". * * It makes the response ineligible for serving other clients. * * @return Response * * @api */ public function setPrivate() { $this->headers->removeCacheControlDirective('public'); $this->headers->addCacheControlDirective('private'); return $this; } /** * Marks the response as "public". * * It makes the response eligible for serving other clients. * * @return Response * * @api */ public function setPublic() { $this->headers->addCacheControlDirective('public'); $this->headers->removeCacheControlDirective('private'); return $this; } /** * Returns true if the response must be revalidated by caches. * * This method indicates that the response must not be served stale by a * cache in any circumstance without first revalidating with the origin. * When present, the TTL of the response should not be overridden to be * greater than the value provided by the origin. * * @return Boolean true if the response must be revalidated by a cache, false otherwise * * @api */ public function mustRevalidate() { return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->has('proxy-revalidate'); } /** * Returns the Date header as a DateTime instance. * * @return \DateTime A \DateTime instance * * @throws \RuntimeException When the header is not parseable * * @api */ public function getDate() { return $this->headers->getDate('Date', new \DateTime()); } /** * Sets the Date header. * * @param \DateTime $date A \DateTime instance * * @return Response * * @api */ public function setDate(\DateTime $date) { $date->setTimezone(new \DateTimeZone('UTC')); $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT'); return $this; } /** * Returns the age of the response. * * @return integer The age of the response in seconds */ public function getAge() { if (null !== $age = $this->headers->get('Age')) { return (int) $age; } return max(time() - $this->getDate()->format('U'), 0); } /** * Marks the response stale by setting the Age header to be equal to the maximum age of the response. * * @return Response * * @api */ public function expire() { if ($this->isFresh()) { $this->headers->set('Age', $this->getMaxAge()); } return $this; } /** * Returns the value of the Expires header as a DateTime instance. * * @return \DateTime|null A DateTime instance or null if the header does not exist * * @api */ public function getExpires() { try { return $this->headers->getDate('Expires'); } catch (\RuntimeException $e) { // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past return \DateTime::createFromFormat(DATE_RFC2822, 'Sat, 01 Jan 00 00:00:00 +0000'); } } /** * Sets the Expires HTTP header with a DateTime instance. * * Passing null as value will remove the header. * * @param \DateTime|null $date A \DateTime instance or null to remove the header * * @return Response * * @api */ public function setExpires(\DateTime $date = null) { if (null === $date) { $this->headers->remove('Expires'); } else { $date = clone $date; $date->setTimezone(new \DateTimeZone('UTC')); $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT'); } return $this; } /** * Returns the number of seconds after the time specified in the response's Date * header when the response should no longer be considered fresh. * * First, it checks for a s-maxage directive, then a max-age directive, and then it falls * back on an expires header. It returns null when no maximum age can be established. * * @return integer|null Number of seconds * * @api */ public function getMaxAge() { if ($this->headers->hasCacheControlDirective('s-maxage')) { return (int) $this->headers->getCacheControlDirective('s-maxage'); } if ($this->headers->hasCacheControlDirective('max-age')) { return (int) $this->headers->getCacheControlDirective('max-age'); } if (null !== $this->getExpires()) { return $this->getExpires()->format('U') - $this->getDate()->format('U'); } return null; } /** * Sets the number of seconds after which the response should no longer be considered fresh. * * This methods sets the Cache-Control max-age directive. * * @param integer $value Number of seconds * * @return Response * * @api */ public function setMaxAge($value) { $this->headers->addCacheControlDirective('max-age', $value); return $this; } /** * Sets the number of seconds after which the response should no longer be considered fresh by shared caches. * * This methods sets the Cache-Control s-maxage directive. * * @param integer $value Number of seconds * * @return Response * * @api */ public function setSharedMaxAge($value) { $this->setPublic(); $this->headers->addCacheControlDirective('s-maxage', $value); return $this; } /** * Returns the response's time-to-live in seconds. * * It returns null when no freshness information is present in the response. * * When the responses TTL is <= 0, the response may not be served from cache without first * revalidating with the origin. * * @return integer|null The TTL in seconds * * @api */ public function getTtl() { if (null !== $maxAge = $this->getMaxAge()) { return $maxAge - $this->getAge(); } return null; } /** * Sets the response's time-to-live for shared caches. * * This method adjusts the Cache-Control/s-maxage directive. * * @param integer $seconds Number of seconds * * @return Response * * @api */ public function setTtl($seconds) { $this->setSharedMaxAge($this->getAge() + $seconds); return $this; } /** * Sets the response's time-to-live for private/client caches. * * This method adjusts the Cache-Control/max-age directive. * * @param integer $seconds Number of seconds * * @return Response * * @api */ public function setClientTtl($seconds) { $this->setMaxAge($this->getAge() + $seconds); return $this; } /** * Returns the Last-Modified HTTP header as a DateTime instance. * * @return \DateTime|null A DateTime instance or null if the header does not exist * * @throws \RuntimeException When the HTTP header is not parseable * * @api */ public function getLastModified() { return $this->headers->getDate('Last-Modified'); } /** * Sets the Last-Modified HTTP header with a DateTime instance. * * Passing null as value will remove the header. * * @param \DateTime|null $date A \DateTime instance or null to remove the header * * @return Response * * @api */ public function setLastModified(\DateTime $date = null) { if (null === $date) { $this->headers->remove('Last-Modified'); } else { $date = clone $date; $date->setTimezone(new \DateTimeZone('UTC')); $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT'); } return $this; } /** * Returns the literal value of the ETag HTTP header. * * @return string|null The ETag HTTP header or null if it does not exist * * @api */ public function getEtag() { return $this->headers->get('ETag'); } /** * Sets the ETag value. * * @param string|null $etag The ETag unique identifier or null to remove the header * @param Boolean $weak Whether you want a weak ETag or not * * @return Response * * @api */ public function setEtag($etag = null, $weak = false) { if (null === $etag) { $this->headers->remove('Etag'); } else { if (0 !== strpos($etag, '"')) { $etag = '"'.$etag.'"'; } $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag); } return $this; } /** * Sets the response's cache headers (validation and/or expiration). * * Available options are: etag, last_modified, max_age, s_maxage, private, and public. * * @param array $options An array of cache options * * @return Response * * @throws \InvalidArgumentException * * @api */ public function setCache(array $options) { if ($diff = array_diff(array_keys($options), array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public'))) { throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', array_values($diff)))); } if (isset($options['etag'])) { $this->setEtag($options['etag']); } if (isset($options['last_modified'])) { $this->setLastModified($options['last_modified']); } if (isset($options['max_age'])) { $this->setMaxAge($options['max_age']); } if (isset($options['s_maxage'])) { $this->setSharedMaxAge($options['s_maxage']); } if (isset($options['public'])) { if ($options['public']) { $this->setPublic(); } else { $this->setPrivate(); } } if (isset($options['private'])) { if ($options['private']) { $this->setPrivate(); } else { $this->setPublic(); } } return $this; } /** * Modifies the response so that it conforms to the rules defined for a 304 status code. * * This sets the status, removes the body, and discards any headers * that MUST NOT be included in 304 responses. * * @return Response * * @see http://tools.ietf.org/html/rfc2616#section-10.3.5 * * @api */ public function setNotModified() { $this->setStatusCode(304); $this->setContent(null); // remove headers that MUST NOT be included with 304 Not Modified responses foreach (array('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified') as $header) { $this->headers->remove($header); } return $this; } /** * Returns true if the response includes a Vary header. * * @return Boolean true if the response includes a Vary header, false otherwise * * @api */ public function hasVary() { return null !== $this->headers->get('Vary'); } /** * Returns an array of header names given in the Vary header. * * @return array An array of Vary names * * @api */ public function getVary() { if (!$vary = $this->headers->get('Vary', null, false)) { return array(); } $ret = array(); foreach ($vary as $item) { $ret = array_merge($ret, preg_split('/[\s,]+/', $item)); } return $ret; } /** * Sets the Vary header. * * @param string|array $headers * @param Boolean $replace Whether to replace the actual value of not (true by default) * * @return Response * * @api */ public function setVary($headers, $replace = true) { $this->headers->set('Vary', $headers, $replace); return $this; } /** * Determines if the Response validators (ETag, Last-Modified) match * a conditional value specified in the Request. * * If the Response is not modified, it sets the status code to 304 and * removes the actual content by calling the setNotModified() method. * * @param Request $request A Request instance * * @return Boolean true if the Response validators match the Request, false otherwise * * @api */ public function isNotModified(Request $request) { if (!$request->isMethodSafe()) { return false; } $lastModified = $request->headers->get('If-Modified-Since'); $notModified = false; if ($etags = $request->getEtags()) { $notModified = (in_array($this->getEtag(), $etags) || in_array('*', $etags)) && (!$lastModified || $this->headers->get('Last-Modified') == $lastModified); } elseif ($lastModified) { $notModified = $lastModified == $this->headers->get('Last-Modified'); } if ($notModified) { $this->setNotModified(); } return $notModified; } // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html /** * Is response invalid? * * @return Boolean * * @api */ public function isInvalid() { return $this->statusCode < 100 || $this->statusCode >= 600; } /** * Is response informative? * * @return Boolean * * @api */ public function isInformational() { return $this->statusCode >= 100 && $this->statusCode < 200; } /** * Is response successful? * * @return Boolean * * @api */ public function isSuccessful() { return $this->statusCode >= 200 && $this->statusCode < 300; } /** * Is the response a redirect? * * @return Boolean * * @api */ public function isRedirection() { return $this->statusCode >= 300 && $this->statusCode < 400; } /** * Is there a client error? * * @return Boolean * * @api */ public function isClientError() { return $this->statusCode >= 400 && $this->statusCode < 500; } /** * Was there a server side error? * * @return Boolean * * @api */ public function isServerError() { return $this->statusCode >= 500 && $this->statusCode < 600; } /** * Is the response OK? * * @return Boolean * * @api */ public function isOk() { return 200 === $this->statusCode; } /** * Is the response forbidden? * * @return Boolean * * @api */ public function isForbidden() { return 403 === $this->statusCode; } /** * Is the response a not found error? * * @return Boolean * * @api */ public function isNotFound() { return 404 === $this->statusCode; } /** * Is the response a redirect of some form? * * @param string $location * * @return Boolean * * @api */ public function isRedirect($location = null) { return in_array($this->statusCode, array(201, 301, 302, 303, 307, 308)) && (null === $location ?: $location == $this->headers->get('Location')); } /** * Is the response empty? * * @return Boolean * * @api */ public function isEmpty() { return in_array($this->statusCode, array(201, 204, 304)); } /** * Check if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9 * * @link http://support.microsoft.com/kb/323308 */ protected function ensureIEOverSSLCompatibility(Request $request) { if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) { if (intval(preg_replace("/(MSIE )(.*?);/", "$2", $match[0])) < 9) { $this->headers->remove('Cache-Control'); } } } } PK]\8HttpFoundation/ParameterBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * ParameterBag is a container for key/value pairs. * * @author Fabien Potencier * * @api */ class ParameterBag implements \IteratorAggregate, \Countable { /** * Parameter storage. * * @var array */ protected $parameters; /** * Constructor. * * @param array $parameters An array of parameters * * @api */ public function __construct(array $parameters = array()) { $this->parameters = $parameters; } /** * Returns the parameters. * * @return array An array of parameters * * @api */ public function all() { return $this->parameters; } /** * Returns the parameter keys. * * @return array An array of parameter keys * * @api */ public function keys() { return array_keys($this->parameters); } /** * Replaces the current parameters by a new set. * * @param array $parameters An array of parameters * * @api */ public function replace(array $parameters = array()) { $this->parameters = $parameters; } /** * Adds parameters. * * @param array $parameters An array of parameters * * @api */ public function add(array $parameters = array()) { $this->parameters = array_replace($this->parameters, $parameters); } /** * Returns a parameter by name. * * @param string $path The key * @param mixed $default The default value if the parameter key does not exist * @param boolean $deep If true, a path like foo[bar] will find deeper items * * @return mixed * * @throws \InvalidArgumentException * * @api */ public function get($path, $default = null, $deep = false) { if (!$deep || false === $pos = strpos($path, '[')) { return array_key_exists($path, $this->parameters) ? $this->parameters[$path] : $default; } $root = substr($path, 0, $pos); if (!array_key_exists($root, $this->parameters)) { return $default; } $value = $this->parameters[$root]; $currentKey = null; for ($i = $pos, $c = strlen($path); $i < $c; $i++) { $char = $path[$i]; if ('[' === $char) { if (null !== $currentKey) { throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "[" at position %d.', $i)); } $currentKey = ''; } elseif (']' === $char) { if (null === $currentKey) { throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "]" at position %d.', $i)); } if (!is_array($value) || !array_key_exists($currentKey, $value)) { return $default; } $value = $value[$currentKey]; $currentKey = null; } else { if (null === $currentKey) { throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "%s" at position %d.', $char, $i)); } $currentKey .= $char; } } if (null !== $currentKey) { throw new \InvalidArgumentException(sprintf('Malformed path. Path must end with "]".')); } return $value; } /** * Sets a parameter by name. * * @param string $key The key * @param mixed $value The value * * @api */ public function set($key, $value) { $this->parameters[$key] = $value; } /** * Returns true if the parameter is defined. * * @param string $key The key * * @return Boolean true if the parameter exists, false otherwise * * @api */ public function has($key) { return array_key_exists($key, $this->parameters); } /** * Removes a parameter. * * @param string $key The key * * @api */ public function remove($key) { unset($this->parameters[$key]); } /** * Returns the alphabetic characters of the parameter value. * * @param string $key The parameter key * @param mixed $default The default value if the parameter key does not exist * @param boolean $deep If true, a path like foo[bar] will find deeper items * * @return string The filtered value * * @api */ public function getAlpha($key, $default = '', $deep = false) { return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default, $deep)); } /** * Returns the alphabetic characters and digits of the parameter value. * * @param string $key The parameter key * @param mixed $default The default value if the parameter key does not exist * @param boolean $deep If true, a path like foo[bar] will find deeper items * * @return string The filtered value * * @api */ public function getAlnum($key, $default = '', $deep = false) { return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default, $deep)); } /** * Returns the digits of the parameter value. * * @param string $key The parameter key * @param mixed $default The default value if the parameter key does not exist * @param boolean $deep If true, a path like foo[bar] will find deeper items * * @return string The filtered value * * @api */ public function getDigits($key, $default = '', $deep = false) { // we need to remove - and + because they're allowed in the filter return str_replace(array('-', '+'), '', $this->filter($key, $default, $deep, FILTER_SANITIZE_NUMBER_INT)); } /** * Returns the parameter value converted to integer. * * @param string $key The parameter key * @param mixed $default The default value if the parameter key does not exist * @param boolean $deep If true, a path like foo[bar] will find deeper items * * @return integer The filtered value * * @api */ public function getInt($key, $default = 0, $deep = false) { return (int) $this->get($key, $default, $deep); } /** * Filter key. * * @param string $key Key. * @param mixed $default Default = null. * @param boolean $deep Default = false. * @param integer $filter FILTER_* constant. * @param mixed $options Filter options. * * @see http://php.net/manual/en/function.filter-var.php * * @return mixed */ public function filter($key, $default = null, $deep = false, $filter = FILTER_DEFAULT, $options = array()) { $value = $this->get($key, $default, $deep); // Always turn $options into an array - this allows filter_var option shortcuts. if (!is_array($options) && $options) { $options = array('flags' => $options); } // Add a convenience check for arrays. if (is_array($value) && !isset($options['flags'])) { $options['flags'] = FILTER_REQUIRE_ARRAY; } return filter_var($value, $filter, $options); } /** * Returns an iterator for parameters. * * @return \ArrayIterator An \ArrayIterator instance */ public function getIterator() { return new \ArrayIterator($this->parameters); } /** * Returns the number of parameters. * * @return int The number of parameters */ public function count() { return count($this->parameters); } } PK]s #HttpFoundation/StreamedResponse.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * StreamedResponse represents a streamed HTTP response. * * A StreamedResponse uses a callback for its content. * * The callback should use the standard PHP functions like echo * to stream the response back to the client. The flush() method * can also be used if needed. * * @see flush() * * @author Fabien Potencier * * @api */ class StreamedResponse extends Response { protected $callback; protected $streamed; /** * Constructor. * * @param callable|null $callback A valid PHP callback or null to set it later * @param integer $status The response status code * @param array $headers An array of response headers * * @api */ public function __construct($callback = null, $status = 200, $headers = array()) { parent::__construct(null, $status, $headers); if (null !== $callback) { $this->setCallback($callback); } $this->streamed = false; } /** * Factory method for chainability * * @param callable|null $callback A valid PHP callback or null to set it later * @param integer $status The response status code * @param array $headers An array of response headers * * @return StreamedResponse */ public static function create($callback = null, $status = 200, $headers = array()) { return new static($callback, $status, $headers); } /** * Sets the PHP callback associated with this Response. * * @param callable $callback A valid PHP callback * * @throws \LogicException */ public function setCallback($callback) { if (!is_callable($callback)) { throw new \LogicException('The Response callback must be a valid PHP callable.'); } $this->callback = $callback; } /** * {@inheritdoc} */ public function prepare(Request $request) { $this->headers->set('Cache-Control', 'no-cache'); return parent::prepare($request); } /** * {@inheritdoc} * * This method only sends the content once. */ public function sendContent() { if ($this->streamed) { return; } $this->streamed = true; if (null === $this->callback) { throw new \LogicException('The Response callback must not be null.'); } call_user_func($this->callback); } /** * {@inheritdoc} * * @throws \LogicException when the content is not null */ public function setContent($content) { if (null !== $content) { throw new \LogicException('The content cannot be set on a StreamedResponse instance.'); } } /** * {@inheritdoc} * * @return false */ public function getContent() { return false; } } PK]a.HttpFoundation/AcceptHeader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Represents an Accept-* header. * * An accept header is compound with a list of items, * sorted by descending quality. * * @author Jean-François Simon */ class AcceptHeader { /** * @var AcceptHeaderItem[] */ private $items = array(); /** * @var bool */ private $sorted = true; /** * Constructor. * * @param AcceptHeaderItem[] $items */ public function __construct(array $items) { foreach ($items as $item) { $this->add($item); } } /** * Builds an AcceptHeader instance from a string. * * @param string $headerValue * * @return AcceptHeader */ public static function fromString($headerValue) { $index = 0; return new self(array_map(function ($itemValue) use (&$index) { $item = AcceptHeaderItem::fromString($itemValue); $item->setIndex($index++); return $item; }, preg_split('/\s*(?:,*("[^"]+"),*|,*(\'[^\']+\'),*|,+)\s*/', $headerValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE))); } /** * Returns header value's string representation. * * @return string */ public function __toString() { return implode(',', $this->items); } /** * Tests if header has given value. * * @param string $value * * @return Boolean */ public function has($value) { return isset($this->items[$value]); } /** * Returns given value's item, if exists. * * @param string $value * * @return AcceptHeaderItem|null */ public function get($value) { return isset($this->items[$value]) ? $this->items[$value] : null; } /** * Adds an item. * * @param AcceptHeaderItem $item * * @return AcceptHeader */ public function add(AcceptHeaderItem $item) { $this->items[$item->getValue()] = $item; $this->sorted = false; return $this; } /** * Returns all items. * * @return AcceptHeaderItem[] */ public function all() { $this->sort(); return $this->items; } /** * Filters items on their value using given regex. * * @param string $pattern * * @return AcceptHeader */ public function filter($pattern) { return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) { return preg_match($pattern, $item->getValue()); })); } /** * Returns first item. * * @return AcceptHeaderItem|null */ public function first() { $this->sort(); return !empty($this->items) ? reset($this->items) : null; } /** * Sorts items by descending quality */ private function sort() { if (!$this->sorted) { uasort($this->items, function ($a, $b) { $qA = $a->getQuality(); $qB = $b->getQuality(); if ($qA === $qB) { return $a->getIndex() > $b->getIndex() ? 1 : -1; } return $qA > $qB ? -1 : 1; }); $this->sorted = true; } } } PK]͢|HttpFoundation/JsonResponse.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Response represents an HTTP response in JSON format. * * Note that this class does not force the returned JSON content to be an * object. It is however recommended that you do return an object as it * protects yourself against XSSI and JSON-JavaScript Hijacking. * * @see https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outside * * @author Igor Wiedler */ class JsonResponse extends Response { protected $data; protected $callback; /** * Constructor. * * @param mixed $data The response data * @param integer $status The response status code * @param array $headers An array of response headers */ public function __construct($data = null, $status = 200, $headers = array()) { parent::__construct('', $status, $headers); if (null === $data) { $data = new \ArrayObject(); } $this->setData($data); } /** * {@inheritDoc} */ public static function create($data = null, $status = 200, $headers = array()) { return new static($data, $status, $headers); } /** * Sets the JSONP callback. * * @param string|null $callback The JSONP callback or null to use none * * @return JsonResponse * * @throws \InvalidArgumentException When the callback name is not valid */ public function setCallback($callback = null) { if (null !== $callback) { // taken from http://www.geekality.net/2011/08/03/valid-javascript-identifier/ $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*+$/u'; $parts = explode('.', $callback); foreach ($parts as $part) { if (!preg_match($pattern, $part)) { throw new \InvalidArgumentException('The callback name is not valid.'); } } } $this->callback = $callback; return $this->update(); } /** * Sets the data to be sent as json. * * @param mixed $data * * @return JsonResponse * * @throws \InvalidArgumentException */ public function setData($data = array()) { // Encode <, >, ', &, and " for RFC4627-compliant JSON, which may also be embedded into HTML. $this->data = json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT); if (JSON_ERROR_NONE !== json_last_error()) { throw new \InvalidArgumentException($this->transformJsonError()); } return $this->update(); } /** * Updates the content and headers according to the json data and callback. * * @return JsonResponse */ protected function update() { if (null !== $this->callback) { // Not using application/javascript for compatibility reasons with older browsers. $this->headers->set('Content-Type', 'text/javascript'); return $this->setContent(sprintf('%s(%s);', $this->callback, $this->data)); } // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback) // in order to not overwrite a custom definition. if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) { $this->headers->set('Content-Type', 'application/json'); } return $this->setContent($this->data); } private function transformJsonError() { if (function_exists('json_last_error_msg')) { return json_last_error_msg(); } switch (json_last_error()) { case JSON_ERROR_DEPTH: return 'Maximum stack depth exceeded.'; case JSON_ERROR_STATE_MISMATCH: return 'Underflow or the modes mismatch.'; case JSON_ERROR_CTRL_CHAR: return 'Unexpected control character found.'; case JSON_ERROR_SYNTAX: return 'Syntax error, malformed JSON.'; case JSON_ERROR_UTF8: return 'Malformed UTF-8 characters, possibly incorrectly encoded.'; default: return 'Unknown error.'; } } } PK]PiHttpFoundation/FileBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\File\UploadedFile; /** * FileBag is a container for uploaded files. * * @author Fabien Potencier * @author Bulat Shakirzyanov * * @api */ class FileBag extends ParameterBag { private static $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); /** * Constructor. * * @param array $parameters An array of HTTP files * * @api */ public function __construct(array $parameters = array()) { $this->replace($parameters); } /** * {@inheritdoc} * * @api */ public function replace(array $files = array()) { $this->parameters = array(); $this->add($files); } /** * {@inheritdoc} * * @api */ public function set($key, $value) { if (!is_array($value) && !$value instanceof UploadedFile) { throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.'); } parent::set($key, $this->convertFileInformation($value)); } /** * {@inheritdoc} * * @api */ public function add(array $files = array()) { foreach ($files as $key => $file) { $this->set($key, $file); } } /** * Converts uploaded files to UploadedFile instances. * * @param array|UploadedFile $file A (multi-dimensional) array of uploaded file information * * @return array A (multi-dimensional) array of UploadedFile instances */ protected function convertFileInformation($file) { if ($file instanceof UploadedFile) { return $file; } $file = $this->fixPhpFilesArray($file); if (is_array($file)) { $keys = array_keys($file); sort($keys); if ($keys == self::$fileKeys) { if (UPLOAD_ERR_NO_FILE == $file['error']) { $file = null; } else { $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']); } } else { $file = array_map(array($this, 'convertFileInformation'), $file); } } return $file; } /** * Fixes a malformed PHP $_FILES array. * * PHP has a bug that the format of the $_FILES array differs, depending on * whether the uploaded file fields had normal field names or array-like * field names ("normal" vs. "parent[child]"). * * This method fixes the array to look like the "normal" $_FILES array. * * It's safe to pass an already converted array, in which case this method * just returns the original array unmodified. * * @param array $data * * @return array */ protected function fixPhpFilesArray($data) { if (!is_array($data)) { return $data; } $keys = array_keys($data); sort($keys); if (self::$fileKeys != $keys || !isset($data['name']) || !is_array($data['name'])) { return $data; } $files = $data; foreach (self::$fileKeys as $k) { unset($files[$k]); } foreach (array_keys($data['name']) as $key) { $files[$key] = $this->fixPhpFilesArray(array( 'error' => $data['error'][$key], 'name' => $data['name'][$key], 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key] )); } return $files; } } PK]_DK #HttpFoundation/RedirectResponse.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * RedirectResponse represents an HTTP response doing a redirect. * * @author Fabien Potencier * * @api */ class RedirectResponse extends Response { protected $targetUrl; /** * Creates a redirect response so that it conforms to the rules defined for a redirect status code. * * @param string $url The URL to redirect to * @param integer $status The status code (302 by default) * @param array $headers The headers (Location is always set to the given URL) * * @throws \InvalidArgumentException * * @see http://tools.ietf.org/html/rfc2616#section-10.3 * * @api */ public function __construct($url, $status = 302, $headers = array()) { if (empty($url)) { throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); } parent::__construct('', $status, $headers); $this->setTargetUrl($url); if (!$this->isRedirect()) { throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status)); } } /** * {@inheritDoc} */ public static function create($url = '', $status = 302, $headers = array()) { return new static($url, $status, $headers); } /** * Returns the target URL. * * @return string target URL */ public function getTargetUrl() { return $this->targetUrl; } /** * Sets the redirect target of this response. * * @param string $url The URL to redirect to * * @return RedirectResponse The current response. * * @throws \InvalidArgumentException */ public function setTargetUrl($url) { if (empty($url)) { throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); } $this->targetUrl = $url; $this->setContent( sprintf(' Redirecting to %1$s Redirecting to %1$s. ', htmlspecialchars($url, ENT_QUOTES, 'UTF-8'))); $this->headers->set('Location', $url); return $this; } } PK]7 E E HttpFoundation/RequestStack.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Request stack that controls the lifecycle of requests. * * @author Benjamin Eberlei */ class RequestStack { /** * @var Request[] */ private $requests = array(); /** * Pushes a Request on the stack. * * This method should generally not be called directly as the stack * management should be taken care of by the application itself. */ public function push(Request $request) { $this->requests[] = $request; } /** * Pops the current request from the stack. * * This operation lets the current request go out of scope. * * This method should generally not be called directly as the stack * management should be taken care of by the application itself. * * @return Request|null */ public function pop() { if (!$this->requests) { return null; } return array_pop($this->requests); } /** * @return Request|null */ public function getCurrentRequest() { return end($this->requests) ?: null; } /** * Gets the master Request. * * Be warned that making your code aware of the master request * might make it un-compatible with other features of your framework * like ESI support. * * @return Request|null */ public function getMasterRequest() { if (!$this->requests) { return null; } return $this->requests[0]; } /** * Returns the parent request of the current. * * Be warned that making your code aware of the parent request * might make it un-compatible with other features of your framework * like ESI support. * * If current Request is the master request, it returns null. * * @return Request|null */ public function getParentRequest() { $pos = count($this->requests) - 2; if (!isset($this->requests[$pos])) { return null; } return $this->requests[$pos]; } } PK]PE XXHttpFoundation/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\InvalidArgumentException; use Symfony\Component\Process\Exception\LogicException; /** * Process builder. * * @author Kris Wallsmith */ class ProcessBuilder { private $arguments; private $cwd; private $env = array(); private $stdin; private $timeout = 60; private $options = array(); private $inheritEnv = true; private $prefix = array(); public function __construct(array $arguments = array()) { $this->arguments = $arguments; } public static function create(array $arguments = array()) { return new static($arguments); } /** * Adds an unescaped argument to the command string. * * @param string $argument A command argument * * @return ProcessBuilder */ public function add($argument) { $this->arguments[] = $argument; return $this; } /** * Adds an unescaped prefix to the command string. * * The prefix is preserved when resetting arguments. * * @param string|array $prefix A command prefix or an array of command prefixes * * @return ProcessBuilder */ public function setPrefix($prefix) { $this->prefix = is_array($prefix) ? $prefix : array($prefix); return $this; } /** * @param array $arguments * * @return ProcessBuilder */ public function setArguments(array $arguments) { $this->arguments = $arguments; return $this; } public function setWorkingDirectory($cwd) { $this->cwd = $cwd; return $this; } public function inheritEnvironmentVariables($inheritEnv = true) { $this->inheritEnv = $inheritEnv; return $this; } public function setEnv($name, $value) { $this->env[$name] = $value; return $this; } public function addEnvironmentVariables(array $variables) { $this->env = array_replace($this->env, $variables); return $this; } public function setInput($stdin) { $this->stdin = $stdin; return $this; } /** * Sets the process timeout. * * To disable the timeout, set this value to null. * * @param float|null * * @return ProcessBuilder * * @throws InvalidArgumentException */ public function setTimeout($timeout) { if (null === $timeout) { $this->timeout = null; return $this; } $timeout = (float) $timeout; if ($timeout < 0) { throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.'); } $this->timeout = $timeout; return $this; } public function setOption($name, $value) { $this->options[$name] = $value; return $this; } public function getProcess() { if (0 === count($this->prefix) && 0 === count($this->arguments)) { throw new LogicException('You must add() command arguments before calling getProcess().'); } $options = $this->options; $arguments = array_merge($this->prefix, $this->arguments); $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments)); if ($this->inheritEnv) { // include $_ENV for BC purposes $env = array_replace($_ENV, $_SERVER, $this->env); } else { $env = $this->env; } return new Process($script, $this->cwd, $env, $this->stdin, $this->timeout, $options); } } PK]nL L Process/ProcessUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; /** * ProcessUtils is a bunch of utility methods. * * This class contains static methods only and is not meant to be instantiated. * * @author Martin Hasoň */ class ProcessUtils { /** * This class should not be instantiated */ private function __construct() { } /** * Escapes a string to be used as a shell argument. * * @param string $argument The argument that will be escaped * * @return string The escaped argument */ public static function escapeArgument($argument) { //Fix for PHP bug #43784 escapeshellarg removes % from given string //Fix for PHP bug #49446 escapeshellarg doesn't work on Windows //@see https://bugs.php.net/bug.php?id=43784 //@see https://bugs.php.net/bug.php?id=49446 if (defined('PHP_WINDOWS_VERSION_BUILD')) { if ('' === $argument) { return escapeshellarg($argument); } $escapedArgument = ''; $quote = false; foreach (preg_split('/(")/i', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) { if ('"' === $part) { $escapedArgument .= '\\"'; } elseif (self::isSurroundedBy($part, '%')) { // Avoid environment variable expansion $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%'; } else { // escape trailing backslash if ('\\' === substr($part, -1)) { $part .= '\\'; } $quote = true; $escapedArgument .= $part; } } if ($quote) { $escapedArgument = '"'.$escapedArgument.'"'; } return $escapedArgument; } return escapeshellarg($argument); } private static function isSurroundedBy($arg, $char) { return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1]; } } PK]@sProcess/PhpProcess.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\RuntimeException; /** * PhpProcess runs a PHP script in an independent process. * * $p = new PhpProcess(''); * $p->run(); * print $p->getOutput()."\n"; * * @author Fabien Potencier * * @api */ class PhpProcess extends Process { private $executableFinder; /** * Constructor. * * @param string $script The PHP script to run (as a string) * @param string $cwd The working directory * @param array $env The environment variables * @param integer $timeout The timeout in seconds * @param array $options An array of options for proc_open * * @api */ public function __construct($script, $cwd = null, array $env = array(), $timeout = 60, array $options = array()) { parent::__construct(null, $cwd, $env, $script, $timeout, $options); $this->executableFinder = new PhpExecutableFinder(); } /** * Sets the path to the PHP binary to use. * * @api */ public function setPhpBinary($php) { $this->setCommandLine($php); } /** * {@inheritdoc} */ public function start($callback = null) { if (null === $this->getCommandLine()) { if (false === $php = $this->executableFinder->find()) { throw new RuntimeException('Unable to find the PHP executable.'); } $this->setCommandLine($php); } parent::start($callback); } } PK]!,$  Process/ExecutableFinder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; /** * Generic executable finder. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class ExecutableFinder { private $suffixes = array('.exe', '.bat', '.cmd', '.com'); /** * Replaces default suffixes of executable. * * @param array $suffixes */ public function setSuffixes(array $suffixes) { $this->suffixes = $suffixes; } /** * Adds new possible suffix to check for executable. * * @param string $suffix */ public function addSuffix($suffix) { $this->suffixes[] = $suffix; } /** * Finds an executable by name. * * @param string $name The executable name (without the extension) * @param string $default The default to return if no executable is found * @param array $extraDirs Additional dirs to check into * * @return string The executable path or default value */ public function find($name, $default = null, array $extraDirs = array()) { if (ini_get('open_basedir')) { $searchPath = explode(PATH_SEPARATOR, getenv('open_basedir')); $dirs = array(); foreach ($searchPath as $path) { if (is_dir($path)) { $dirs[] = $path; } else { $file = str_replace(dirname($path), '', $path); if ($file == $name && is_executable($path)) { return $path; } } } } else { $dirs = array_merge( explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), $extraDirs ); } $suffixes = array(''); if (defined('PHP_WINDOWS_VERSION_BUILD')) { $pathExt = getenv('PATHEXT'); $suffixes = $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes; } foreach ($suffixes as $suffix) { foreach ($dirs as $dir) { if (is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && (defined('PHP_WINDOWS_VERSION_BUILD') || is_executable($file))) { return $file; } } } return $default; } } PK]W$Process/Exception/LogicException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * LogicException for the Process Component. * * @author Romain Neutron */ class LogicException extends \LogicException implements ExceptionInterface { } PK]<(Process/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * Marker Interface for the Process Component. * * @author Johannes M. Schmitt */ interface ExceptionInterface { } PK]>H&Process/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * RuntimeException for the Process Component. * * @author Johannes M. Schmitt */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK]2{{.Process/Exception/ProcessTimedOutException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; use Symfony\Component\Process\Process; /** * Exception that is thrown when a process times out. * * @author Johannes M. Schmitt */ class ProcessTimedOutException extends RuntimeException { const TYPE_GENERAL = 1; const TYPE_IDLE = 2; private $process; private $timeoutType; public function __construct(Process $process, $timeoutType) { $this->process = $process; $this->timeoutType = $timeoutType; parent::__construct(sprintf( 'The process "%s" exceeded the timeout of %s seconds.', $process->getCommandLine(), $this->getExceededTimeout() )); } public function getProcess() { return $this->process; } public function isGeneralTimeout() { return $this->timeoutType === self::TYPE_GENERAL; } public function isIdleTimeout() { return $this->timeoutType === self::TYPE_IDLE; } public function getExceededTimeout() { switch ($this->timeoutType) { case self::TYPE_GENERAL: return $this->process->getTimeout(); case self::TYPE_IDLE: return $this->process->getIdleTimeout(); default: throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType)); } } } PK]_,Process/Exception/ProcessFailedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; use Symfony\Component\Process\Process; /** * Exception for failed processes. * * @author Johannes M. Schmitt */ class ProcessFailedException extends RuntimeException { private $process; public function __construct(Process $process) { if ($process->isSuccessful()) { throw new InvalidArgumentException('Expected a failed process, but the given process was successful.'); } parent::__construct( sprintf( 'The command "%s" failed.'."\nExit Code: %s(%s)\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s", $process->getCommandLine(), $process->getExitCode(), $process->getExitCodeText(), $process->getOutput(), $process->getErrorOutput() ) ); $this->process = $process; } public function getProcess() { return $this->process; } } PK]˅.Process/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * InvalidArgumentException for the Process Component. * * @author Romain Neutron */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PK]g''Process/ProcessPipes.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\RuntimeException; /** * ProcessPipes manages descriptors and pipes for the use of proc_open. */ class ProcessPipes { /** @var array */ public $pipes = array(); /** @var array */ private $files = array(); /** @var array */ private $fileHandles = array(); /** @var array */ private $readBytes = array(); /** @var Boolean */ private $useFiles; /** @var Boolean */ private $ttyMode; const CHUNK_SIZE = 16384; public function __construct($useFiles, $ttyMode) { $this->useFiles = (Boolean) $useFiles; $this->ttyMode = (Boolean) $ttyMode; // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big. // Workaround for this problem is to use temporary files instead of pipes on Windows platform. // // @see https://bugs.php.net/bug.php?id=51800 if ($this->useFiles) { $this->files = array( Process::STDOUT => tempnam(sys_get_temp_dir(), 'sf_proc_stdout'), Process::STDERR => tempnam(sys_get_temp_dir(), 'sf_proc_stderr'), ); foreach ($this->files as $offset => $file) { $this->fileHandles[$offset] = fopen($this->files[$offset], 'rb'); if (false === $this->fileHandles[$offset]) { throw new RuntimeException('A temporary file could not be opened to write the process output to, verify that your TEMP environment variable is writable'); } } $this->readBytes = array( Process::STDOUT => 0, Process::STDERR => 0, ); } } public function __destruct() { $this->close(); $this->removeFiles(); } /** * Sets non-blocking mode on pipes. */ public function unblock() { foreach ($this->pipes as $pipe) { stream_set_blocking($pipe, 0); } } /** * Closes file handles and pipes. */ public function close() { $this->closeUnixPipes(); foreach ($this->fileHandles as $handle) { fclose($handle); } $this->fileHandles = array(); } /** * Closes Unix pipes. * * Nothing happens in case file handles are used. */ public function closeUnixPipes() { foreach ($this->pipes as $pipe) { fclose($pipe); } $this->pipes = array(); } /** * Returns an array of descriptors for the use of proc_open. * * @return array */ public function getDescriptors() { if ($this->useFiles) { // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/bug.php?id=51800) // We're not using file handles as it can produce corrupted output https://bugs.php.net/bug.php?id=65650 // So we redirect output within the commandline and pass the nul device to the process return array( array('pipe', 'r'), array('file', 'NUL', 'w'), array('file', 'NUL', 'w'), ); } if ($this->ttyMode) { return array( array('file', '/dev/tty', 'r'), array('file', '/dev/tty', 'w'), array('file', '/dev/tty', 'w'), ); } return array( array('pipe', 'r'), // stdin array('pipe', 'w'), // stdout array('pipe', 'w'), // stderr ); } /** * Returns an array of filenames indexed by their related stream in case these pipes use temporary files. * * @return array */ public function getFiles() { if ($this->useFiles) { return $this->files; } return array(); } /** * Reads data in file handles and pipes. * * @param Boolean $blocking Whether to use blocking calls or not. * * @return array An array of read data indexed by their fd. */ public function read($blocking) { return array_replace($this->readStreams($blocking), $this->readFileHandles()); } /** * Reads data in file handles and pipes, closes them if EOF is reached. * * @param Boolean $blocking Whether to use blocking calls or not. * * @return array An array of read data indexed by their fd. */ public function readAndCloseHandles($blocking) { return array_replace($this->readStreams($blocking, true), $this->readFileHandles(true)); } /** * Returns if the current state has open file handles or pipes. * * @return Boolean */ public function hasOpenHandles() { if (!$this->useFiles) { return (Boolean) $this->pipes; } return (Boolean) $this->pipes && (Boolean) $this->fileHandles; } /** * Writes stdin data. * * @param Boolean $blocking Whether to use blocking calls or not. * @param string|null $stdin The data to write. */ public function write($blocking, $stdin) { if (null === $stdin) { fclose($this->pipes[0]); unset($this->pipes[0]); return; } $writePipes = array($this->pipes[0]); unset($this->pipes[0]); $stdinLen = strlen($stdin); $stdinOffset = 0; while ($writePipes) { $r = null; $w = $writePipes; $e = null; if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? ceil(Process::TIMEOUT_PRECISION * 1E6) : 0)) { // if a system call has been interrupted, forget about it, let's try again if ($this->hasSystemCallBeenInterrupted()) { continue; } break; } // nothing has changed, let's wait until the process is ready if (0 === $n) { continue; } if ($w) { $written = fwrite($writePipes[0], (binary) substr($stdin, $stdinOffset), 8192); if (false !== $written) { $stdinOffset += $written; } if ($stdinOffset >= $stdinLen) { fclose($writePipes[0]); $writePipes = null; } } } } /** * Reads data in file handles. * * @param Boolean $close Whether to close file handles or not. * * @return array An array of read data indexed by their fd. */ private function readFileHandles($close = false) { $read = array(); $fh = $this->fileHandles; foreach ($fh as $type => $fileHandle) { if (0 !== fseek($fileHandle, $this->readBytes[$type])) { continue; } $data = ''; $dataread = null; while (!feof($fileHandle)) { if (false !== $dataread = fread($fileHandle, self::CHUNK_SIZE)) { $data .= $dataread; } } if (0 < $length = strlen($data)) { $this->readBytes[$type] += $length; $read[$type] = $data; } if (false === $dataread || (true === $close && feof($fileHandle) && '' === $data)) { fclose($this->fileHandles[$type]); unset($this->fileHandles[$type]); } } return $read; } /** * Reads data in file pipes streams. * * @param Boolean $blocking Whether to use blocking calls or not. * @param Boolean $close Whether to close file handles or not. * * @return array An array of read data indexed by their fd. */ private function readStreams($blocking, $close = false) { if (empty($this->pipes)) { return array(); } $read = array(); $r = $this->pipes; $w = null; $e = null; // let's have a look if something changed in streams if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? ceil(Process::TIMEOUT_PRECISION * 1E6) : 0)) { // if a system call has been interrupted, forget about it, let's try again // otherwise, an error occurred, let's reset pipes if (!$this->hasSystemCallBeenInterrupted()) { $this->pipes = array(); } return $read; } // nothing has changed if (0 === $n) { return $read; } foreach ($r as $pipe) { $type = array_search($pipe, $this->pipes); $data = ''; while ($dataread = fread($pipe, self::CHUNK_SIZE)) { $data .= $dataread; } if ($data) { $read[$type] = $data; } if (false === $data || (true === $close && feof($pipe) && '' === $data)) { fclose($this->pipes[$type]); unset($this->pipes[$type]); } } return $read; } /** * Returns true if a system call has been interrupted. * * @return Boolean */ private function hasSystemCallBeenInterrupted() { $lastError = error_get_last(); // stream_select returns false when the `select` system call is interrupted by an incoming signal return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call'); } /** * Removes temporary files */ private function removeFiles() { foreach ($this->files as $filename) { if (file_exists($filename)) { @unlink($filename); } } $this->files = array(); } } PK]MProcess/Process.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\InvalidArgumentException; use Symfony\Component\Process\Exception\LogicException; use Symfony\Component\Process\Exception\ProcessTimedOutException; use Symfony\Component\Process\Exception\RuntimeException; /** * Process is a thin wrapper around proc_* functions to easily * start independent PHP processes. * * @author Fabien Potencier * * @api */ class Process { const ERR = 'err'; const OUT = 'out'; const STATUS_READY = 'ready'; const STATUS_STARTED = 'started'; const STATUS_TERMINATED = 'terminated'; const STDIN = 0; const STDOUT = 1; const STDERR = 2; // Timeout Precision in seconds. const TIMEOUT_PRECISION = 0.2; private $callback; private $commandline; private $cwd; private $env; private $stdin; private $starttime; private $lastOutputTime; private $timeout; private $idleTimeout; private $options; private $exitcode; private $fallbackExitcode; private $processInformation; private $stdout; private $stderr; private $enhanceWindowsCompatibility; private $enhanceSigchildCompatibility; private $process; private $status = self::STATUS_READY; private $incrementalOutputOffset = 0; private $incrementalErrorOutputOffset = 0; private $tty; private $useFileHandles = false; /** @var ProcessPipes */ private $processPipes; private static $sigchild; /** * Exit codes translation table. * * User-defined errors must use exit codes in the 64-113 range. * * @var array */ public static $exitCodes = array( 0 => 'OK', 1 => 'General error', 2 => 'Misuse of shell builtins', 126 => 'Invoked command cannot execute', 127 => 'Command not found', 128 => 'Invalid exit argument', // signals 129 => 'Hangup', 130 => 'Interrupt', 131 => 'Quit and dump core', 132 => 'Illegal instruction', 133 => 'Trace/breakpoint trap', 134 => 'Process aborted', 135 => 'Bus error: "access to undefined portion of memory object"', 136 => 'Floating point exception: "erroneous arithmetic operation"', 137 => 'Kill (terminate immediately)', 138 => 'User-defined 1', 139 => 'Segmentation violation', 140 => 'User-defined 2', 141 => 'Write to pipe with no one reading', 142 => 'Signal raised by alarm', 143 => 'Termination (request to terminate)', // 144 - not defined 145 => 'Child process terminated, stopped (or continued*)', 146 => 'Continue if stopped', 147 => 'Stop executing temporarily', 148 => 'Terminal stop signal', 149 => 'Background process attempting to read from tty ("in")', 150 => 'Background process attempting to write to tty ("out")', 151 => 'Urgent data available on socket', 152 => 'CPU time limit exceeded', 153 => 'File size limit exceeded', 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"', 155 => 'Profiling timer expired', // 156 - not defined 157 => 'Pollable event', // 158 - not defined 159 => 'Bad syscall', ); /** * Constructor. * * @param string $commandline The command line to run * @param string|null $cwd The working directory or null to use the working dir of the current PHP process * @param array|null $env The environment variables or null to inherit * @param string|null $stdin The STDIN content * @param integer|float|null $timeout The timeout in seconds or null to disable * @param array $options An array of options for proc_open * * @throws RuntimeException When proc_open is not installed * * @api */ public function __construct($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array()) { if (!function_exists('proc_open')) { throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.'); } $this->commandline = $commandline; $this->cwd = $cwd; // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected // @see : https://bugs.php.net/bug.php?id=51800 // @see : https://bugs.php.net/bug.php?id=50524 if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || defined('PHP_WINDOWS_VERSION_BUILD'))) { $this->cwd = getcwd(); } if (null !== $env) { $this->setEnv($env); } else { $this->env = null; } $this->stdin = $stdin; $this->setTimeout($timeout); $this->useFileHandles = defined('PHP_WINDOWS_VERSION_BUILD'); $this->enhanceWindowsCompatibility = true; $this->enhanceSigchildCompatibility = !defined('PHP_WINDOWS_VERSION_BUILD') && $this->isSigchildEnabled(); $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options); } public function __destruct() { // stop() will check if we have a process running. $this->stop(); } public function __clone() { $this->resetProcessData(); } /** * Runs the process. * * The callback receives the type of output (out or err) and * some bytes from the output in real-time. It allows to have feedback * from the independent process during execution. * * The STDOUT and STDERR are also available after the process is finished * via the getOutput() and getErrorOutput() methods. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return integer The exit status code * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process stopped after receiving signal * * @api */ public function run($callback = null) { $this->start($callback); return $this->wait(); } /** * Starts the process and returns after sending the STDIN. * * This method blocks until all STDIN data is sent to the process then it * returns while the process runs in the background. * * The termination of the process can be awaited with wait(). * * The callback receives the type of output (out or err) and some bytes from * the output in real-time while writing the standard input to the process. * It allows to have feedback from the independent process during execution. * If there is no callback passed, the wait() method can be called * with true as a second parameter then the callback will get all data occurred * in (and since) the start call. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return Process The process itself * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running */ public function start($callback = null) { if ($this->isRunning()) { throw new RuntimeException('Process is already running'); } $this->resetProcessData(); $this->starttime = $this->lastOutputTime = microtime(true); $this->callback = $this->buildCallback($callback); $descriptors = $this->getDescriptors(); $commandline = $this->commandline; if (defined('PHP_WINDOWS_VERSION_BUILD') && $this->enhanceWindowsCompatibility) { $commandline = 'cmd /V:ON /E:ON /C "('.$commandline.')"'; foreach ($this->processPipes->getFiles() as $offset => $filename) { $commandline .= ' '.$offset.'>'.$filename; } if (!isset($this->options['bypass_shell'])) { $this->options['bypass_shell'] = true; } } $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options); if (!is_resource($this->process)) { throw new RuntimeException('Unable to launch a new process.'); } $this->status = self::STATUS_STARTED; $this->processPipes->unblock(); if ($this->tty) { return; } $this->processPipes->write(false, $this->stdin); $this->updateStatus(false); $this->checkTimeout(); } /** * Restarts the process. * * Be warned that the process is cloned before being started. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return Process The new process * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running * * @see start() */ public function restart($callback = null) { if ($this->isRunning()) { throw new RuntimeException('Process is already running'); } $process = clone $this; $process->start($callback); return $process; } /** * Waits for the process to terminate. * * The callback receives the type of output (out or err) and some bytes * from the output in real-time while writing the standard input to the process. * It allows to have feedback from the independent process during execution. * * @param callable|null $callback A valid PHP callback * * @return integer The exitcode of the process * * @throws RuntimeException When process timed out * @throws RuntimeException When process stopped after receiving signal * @throws LogicException When process is not yet started */ public function wait($callback = null) { $this->requireProcessIsStarted(__FUNCTION__); $this->updateStatus(false); if (null !== $callback) { $this->callback = $this->buildCallback($callback); } do { $this->checkTimeout(); $running = defined('PHP_WINDOWS_VERSION_BUILD') ? $this->isRunning() : $this->processPipes->hasOpenHandles(); $close = !defined('PHP_WINDOWS_VERSION_BUILD') || !$running;; $this->readPipes(true, $close); } while ($running); while ($this->isRunning()) { usleep(1000); } if ($this->processInformation['signaled']) { throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig'])); } return $this->exitcode; } /** * Returns the Pid (process identifier), if applicable. * * @return integer|null The process id if running, null otherwise * * @throws RuntimeException In case --enable-sigchild is activated */ public function getPid() { if ($this->isSigchildEnabled()) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.'); } $this->updateStatus(false); return $this->isRunning() ? $this->processInformation['pid'] : null; } /** * Sends a POSIX signal to the process. * * @param integer $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php) * * @return Process * * @throws LogicException In case the process is not running * @throws RuntimeException In case --enable-sigchild is activated * @throws RuntimeException In case of failure */ public function signal($signal) { $this->doSignal($signal, true); return $this; } /** * Returns the current output of the process (STDOUT). * * @return string The process output * * @throws LogicException In case the process is not started * * @api */ public function getOutput() { $this->requireProcessIsStarted(__FUNCTION__); $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true); return $this->stdout; } /** * Returns the output incrementally. * * In comparison with the getOutput method which always return the whole * output, this one returns the new output since the last call. * * @throws LogicException In case the process is not started * * @return string The process output since the last call */ public function getIncrementalOutput() { $this->requireProcessIsStarted(__FUNCTION__); $data = $this->getOutput(); $latest = substr($data, $this->incrementalOutputOffset); $this->incrementalOutputOffset = strlen($data); return $latest; } /** * Clears the process output. * * @return Process */ public function clearOutput() { $this->stdout = ''; $this->incrementalOutputOffset = 0; return $this; } /** * Returns the current error output of the process (STDERR). * * @return string The process error output * * @throws LogicException In case the process is not started * * @api */ public function getErrorOutput() { $this->requireProcessIsStarted(__FUNCTION__); $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true); return $this->stderr; } /** * Returns the errorOutput incrementally. * * In comparison with the getErrorOutput method which always return the * whole error output, this one returns the new error output since the last * call. * * @throws LogicException In case the process is not started * * @return string The process error output since the last call */ public function getIncrementalErrorOutput() { $this->requireProcessIsStarted(__FUNCTION__); $data = $this->getErrorOutput(); $latest = substr($data, $this->incrementalErrorOutputOffset); $this->incrementalErrorOutputOffset = strlen($data); return $latest; } /** * Clears the process output. * * @return Process */ public function clearErrorOutput() { $this->stderr = ''; $this->incrementalErrorOutputOffset = 0; return $this; } /** * Returns the exit code returned by the process. * * @return null|integer The exit status code, null if the Process is not terminated * * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled * * @api */ public function getExitCode() { if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); } $this->updateStatus(false); return $this->exitcode; } /** * Returns a string representation for the exit code returned by the process. * * This method relies on the Unix exit code status standardization * and might not be relevant for other operating systems. * * @return null|string A string representation for the exit status code, null if the Process is not terminated. * * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled * * @see http://tldp.org/LDP/abs/html/exitcodes.html * @see http://en.wikipedia.org/wiki/Unix_signal */ public function getExitCodeText() { if (null === $exitcode = $this->getExitCode()) { return; } return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error'; } /** * Checks if the process ended successfully. * * @return Boolean true if the process ended successfully, false otherwise * * @api */ public function isSuccessful() { return 0 === $this->getExitCode(); } /** * Returns true if the child process has been terminated by an uncaught signal. * * It always returns false on Windows. * * @return Boolean * * @throws RuntimeException In case --enable-sigchild is activated * @throws LogicException In case the process is not terminated * * @api */ public function hasBeenSignaled() { $this->requireProcessIsTerminated(__FUNCTION__); if ($this->isSigchildEnabled()) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); } $this->updateStatus(false); return $this->processInformation['signaled']; } /** * Returns the number of the signal that caused the child process to terminate its execution. * * It is only meaningful if hasBeenSignaled() returns true. * * @return integer * * @throws RuntimeException In case --enable-sigchild is activated * @throws LogicException In case the process is not terminated * * @api */ public function getTermSignal() { $this->requireProcessIsTerminated(__FUNCTION__); if ($this->isSigchildEnabled()) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); } $this->updateStatus(false); return $this->processInformation['termsig']; } /** * Returns true if the child process has been stopped by a signal. * * It always returns false on Windows. * * @return Boolean * * @throws LogicException In case the process is not terminated * * @api */ public function hasBeenStopped() { $this->requireProcessIsTerminated(__FUNCTION__); $this->updateStatus(false); return $this->processInformation['stopped']; } /** * Returns the number of the signal that caused the child process to stop its execution. * * It is only meaningful if hasBeenStopped() returns true. * * @return integer * * @throws LogicException In case the process is not terminated * * @api */ public function getStopSignal() { $this->requireProcessIsTerminated(__FUNCTION__); $this->updateStatus(false); return $this->processInformation['stopsig']; } /** * Checks if the process is currently running. * * @return Boolean true if the process is currently running, false otherwise */ public function isRunning() { if (self::STATUS_STARTED !== $this->status) { return false; } $this->updateStatus(false); return $this->processInformation['running']; } /** * Checks if the process has been started with no regard to the current state. * * @return Boolean true if status is ready, false otherwise */ public function isStarted() { return $this->status != self::STATUS_READY; } /** * Checks if the process is terminated. * * @return Boolean true if process is terminated, false otherwise */ public function isTerminated() { $this->updateStatus(false); return $this->status == self::STATUS_TERMINATED; } /** * Gets the process status. * * The status is one of: ready, started, terminated. * * @return string The current process status */ public function getStatus() { $this->updateStatus(false); return $this->status; } /** * Stops the process. * * @param integer|float $timeout The timeout in seconds * @param integer $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL * * @return integer The exit-code of the process * * @throws RuntimeException if the process got signaled */ public function stop($timeout = 10, $signal = null) { $timeoutMicro = microtime(true) + $timeout; if ($this->isRunning()) { if (defined('PHP_WINDOWS_VERSION_BUILD') && !$this->isSigchildEnabled()) { exec(sprintf("taskkill /F /T /PID %d 2>&1", $this->getPid()), $output, $exitCode); if ($exitCode > 0) { throw new RuntimeException('Unable to kill the process'); } } proc_terminate($this->process); do { usleep(1000); } while ($this->isRunning() && microtime(true) < $timeoutMicro); if ($this->isRunning() && !$this->isSigchildEnabled()) { if (null !== $signal || defined('SIGKILL')) { // avoid exception here : // process is supposed to be running, but it might have stop // just after this line. // in any case, let's silently discard the error, we can not do anything $this->doSignal($signal ?: SIGKILL, false); } } } $this->updateStatus(false); if ($this->processInformation['running']) { $this->close(); } return $this->exitcode; } /** * Adds a line to the STDOUT stream. * * @param string $line The line to append */ public function addOutput($line) { $this->lastOutputTime = microtime(true); $this->stdout .= $line; } /** * Adds a line to the STDERR stream. * * @param string $line The line to append */ public function addErrorOutput($line) { $this->lastOutputTime = microtime(true); $this->stderr .= $line; } /** * Gets the command line to be executed. * * @return string The command to execute */ public function getCommandLine() { return $this->commandline; } /** * Sets the command line to be executed. * * @param string $commandline The command to execute * * @return self The current Process instance */ public function setCommandLine($commandline) { $this->commandline = $commandline; return $this; } /** * Gets the process timeout (max. runtime). * * @return float|null The timeout in seconds or null if it's disabled */ public function getTimeout() { return $this->timeout; } /** * Gets the process idle timeout (max. time since last output). * * @return float|null The timeout in seconds or null if it's disabled */ public function getIdleTimeout() { return $this->idleTimeout; } /** * Sets the process timeout (max. runtime). * * To disable the timeout, set this value to null. * * @param integer|float|null $timeout The timeout in seconds * * @return self The current Process instance * * @throws InvalidArgumentException if the timeout is negative */ public function setTimeout($timeout) { $this->timeout = $this->validateTimeout($timeout); return $this; } /** * Sets the process idle timeout (max. time since last output). * * To disable the timeout, set this value to null. * * @param integer|float|null $timeout The timeout in seconds * * @return self The current Process instance. * * @throws InvalidArgumentException if the timeout is negative */ public function setIdleTimeout($timeout) { $this->idleTimeout = $this->validateTimeout($timeout); return $this; } /** * Enables or disables the TTY mode. * * @param boolean $tty True to enabled and false to disable * * @return self The current Process instance */ public function setTty($tty) { $this->tty = (Boolean) $tty; return $this; } /** * Checks if the TTY mode is enabled. * * @return Boolean true if the TTY mode is enabled, false otherwise */ public function isTty() { return $this->tty; } /** * Gets the working directory. * * @return string|null The current working directory or null on failure */ public function getWorkingDirectory() { if (null === $this->cwd) { // getcwd() will return false if any one of the parent directories does not have // the readable or search mode set, even if the current directory does return getcwd() ?: null; } return $this->cwd; } /** * Sets the current working directory. * * @param string $cwd The new working directory * * @return self The current Process instance */ public function setWorkingDirectory($cwd) { $this->cwd = $cwd; return $this; } /** * Gets the environment variables. * * @return array The current environment variables */ public function getEnv() { return $this->env; } /** * Sets the environment variables. * * An environment variable value should be a string. * If it is an array, the variable is ignored. * * That happens in PHP when 'argv' is registered into * the $_ENV array for instance. * * @param array $env The new environment variables * * @return self The current Process instance */ public function setEnv(array $env) { // Process can not handle env values that are arrays $env = array_filter($env, function ($value) { return !is_array($value); }); $this->env = array(); foreach ($env as $key => $value) { $this->env[(binary) $key] = (binary) $value; } return $this; } /** * Gets the contents of STDIN. * * @return string|null The current contents */ public function getStdin() { return $this->stdin; } /** * Sets the contents of STDIN. * * @param string|null $stdin The new contents * * @return self The current Process instance */ public function setStdin($stdin) { $this->stdin = $stdin; return $this; } /** * Gets the options for proc_open. * * @return array The current options */ public function getOptions() { return $this->options; } /** * Sets the options for proc_open. * * @param array $options The new options * * @return self The current Process instance */ public function setOptions(array $options) { $this->options = $options; return $this; } /** * Gets whether or not Windows compatibility is enabled. * * This is true by default. * * @return Boolean */ public function getEnhanceWindowsCompatibility() { return $this->enhanceWindowsCompatibility; } /** * Sets whether or not Windows compatibility is enabled. * * @param Boolean $enhance * * @return self The current Process instance */ public function setEnhanceWindowsCompatibility($enhance) { $this->enhanceWindowsCompatibility = (Boolean) $enhance; return $this; } /** * Returns whether sigchild compatibility mode is activated or not. * * @return Boolean */ public function getEnhanceSigchildCompatibility() { return $this->enhanceSigchildCompatibility; } /** * Activates sigchild compatibility mode. * * Sigchild compatibility mode is required to get the exit code and * determine the success of a process when PHP has been compiled with * the --enable-sigchild option * * @param Boolean $enhance * * @return self The current Process instance */ public function setEnhanceSigchildCompatibility($enhance) { $this->enhanceSigchildCompatibility = (Boolean) $enhance; return $this; } /** * Performs a check between the timeout definition and the time the process started. * * In case you run a background process (with the start method), you should * trigger this method regularly to ensure the process timeout * * @throws ProcessTimedOutException In case the timeout was reached */ public function checkTimeout() { if ($this->status !== self::STATUS_STARTED) { return; } if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) { $this->stop(0); throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL); } if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) { $this->stop(0); throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE); } } /** * Creates the descriptors needed by the proc_open. * * @return array */ private function getDescriptors() { $this->processPipes = new ProcessPipes($this->useFileHandles, $this->tty); $descriptors = $this->processPipes->getDescriptors(); if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { // last exit code is output on the fourth pipe and caught to work around --enable-sigchild $descriptors = array_merge($descriptors, array(array('pipe', 'w'))); $this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code'; } return $descriptors; } /** * Builds up the callback used by wait(). * * The callbacks adds all occurred output to the specific buffer and calls * the user callback (if present) with the received output. * * @param callable|null $callback The user defined PHP callback * * @return callable A PHP callable */ protected function buildCallback($callback) { $that = $this; $out = self::OUT; $err = self::ERR; $callback = function ($type, $data) use ($that, $callback, $out, $err) { if ($out == $type) { $that->addOutput($data); } else { $that->addErrorOutput($data); } if (null !== $callback) { call_user_func($callback, $type, $data); } }; return $callback; } /** * Updates the status of the process, reads pipes. * * @param Boolean $blocking Whether to use a blocking read call. */ protected function updateStatus($blocking) { if (self::STATUS_STARTED !== $this->status) { return; } $this->processInformation = proc_get_status($this->process); $this->captureExitCode(); $this->readPipes($blocking, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true); if (!$this->processInformation['running']) { $this->close(); } } /** * Returns whether PHP has been compiled with the '--enable-sigchild' option or not. * * @return Boolean */ protected function isSigchildEnabled() { if (null !== self::$sigchild) { return self::$sigchild; } if (!function_exists('phpinfo')) { return self::$sigchild = false; } ob_start(); phpinfo(INFO_GENERAL); return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild'); } /** * Validates and returns the filtered timeout. * * @param integer|float|null $timeout * * @return float|null */ private function validateTimeout($timeout) { $timeout = (float) $timeout; if (0.0 === $timeout) { $timeout = null; } elseif ($timeout < 0) { throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.'); } return $timeout; } /** * Reads pipes, executes callback. * * @param Boolean $blocking Whether to use blocking calls or not. * @param Boolean $close Whether to close file handles or not. */ private function readPipes($blocking, $close) { if ($close) { $result = $this->processPipes->readAndCloseHandles($blocking); } else { $result = $this->processPipes->read($blocking); } foreach ($result as $type => $data) { if (3 == $type) { $this->fallbackExitcode = (int) $data; } else { call_user_func($this->callback, $type === self::STDOUT ? self::OUT : self::ERR, $data); } } } /** * Captures the exitcode if mentioned in the process information. */ private function captureExitCode() { if (isset($this->processInformation['exitcode']) && -1 != $this->processInformation['exitcode']) { $this->exitcode = $this->processInformation['exitcode']; } } /** * Closes process resource, closes file handles, sets the exitcode. * * @return Integer The exitcode */ private function close() { $this->processPipes->close(); if (is_resource($this->process)) { $exitcode = proc_close($this->process); } else { $exitcode = -1; } $this->exitcode = -1 !== $exitcode ? $exitcode : (null !== $this->exitcode ? $this->exitcode : -1); $this->status = self::STATUS_TERMINATED; if (-1 === $this->exitcode && null !== $this->fallbackExitcode) { $this->exitcode = $this->fallbackExitcode; } elseif (-1 === $this->exitcode && $this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) { // if process has been signaled, no exitcode but a valid termsig, apply Unix convention $this->exitcode = 128 + $this->processInformation['termsig']; } return $this->exitcode; } /** * Resets data related to the latest run of the process. */ private function resetProcessData() { $this->starttime = null; $this->callback = null; $this->exitcode = null; $this->fallbackExitcode = null; $this->processInformation = null; $this->stdout = null; $this->stderr = null; $this->process = null; $this->status = self::STATUS_READY; $this->incrementalOutputOffset = 0; $this->incrementalErrorOutputOffset = 0; } /** * Sends a POSIX signal to the process. * * @param integer $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php) * @param Boolean $throwException Whether to throw exception in case signal failed * * @return Boolean True if the signal was sent successfully, false otherwise * * @throws LogicException In case the process is not running * @throws RuntimeException In case --enable-sigchild is activated * @throws RuntimeException In case of failure */ private function doSignal($signal, $throwException) { if (!$this->isRunning()) { if ($throwException) { throw new LogicException('Can not send signal on a non running process.'); } return false; } if ($this->isSigchildEnabled()) { if ($throwException) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.'); } return false; } if (true !== @proc_terminate($this->process, $signal)) { if ($throwException) { throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal)); } return false; } return true; } /** * Ensures the process is running or terminated, throws a LogicException if the process has a not started. * * @param $functionName The function name that was called. * * @throws LogicException If the process has not run. */ private function requireProcessIsStarted($functionName) { if (!$this->isStarted()) { throw new LogicException(sprintf('Process must be started before calling %s.', $functionName)); } } /** * Ensures the process is terminated, throws a LogicException if the process has a status different than `terminated`. * * @param $functionName The function name that was called. * * @throws LogicException If the process is not yet terminated. */ private function requireProcessIsTerminated($functionName) { if (!$this->isTerminated()) { throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName)); } } } PK]y>8Process/PhpExecutableFinder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; /** * An executable finder specifically designed for the PHP executable. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class PhpExecutableFinder { private $executableFinder; public function __construct() { $this->executableFinder = new ExecutableFinder(); } /** * Finds The PHP executable. * * @return string|false The PHP executable path or false if it cannot be found */ public function find() { // HHVM support if (defined('HHVM_VERSION') && false !== $hhvm = getenv('PHP_BINARY')) { return $hhvm; } // PHP_BINARY return the current sapi executable if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server')) && is_file(PHP_BINARY)) { return PHP_BINARY; } if ($php = getenv('PHP_PATH')) { if (!is_executable($php)) { return false; } return $php; } if ($php = getenv('PHP_PEAR_PHP_BIN')) { if (is_executable($php)) { return $php; } } $dirs = array(PHP_BINDIR); if (defined('PHP_WINDOWS_VERSION_BUILD')) { $dirs[] = 'C:\xampp\php\\'; } return $this->executableFinder->find('php', false, $dirs); } } PK]0QQProcess/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; /** * Request object. * * @author Fabien Potencier * * @api */ class Request { protected $uri; protected $method; protected $parameters; protected $files; protected $cookies; protected $server; protected $content; /** * Constructor. * * @param string $uri The request URI * @param string $method The HTTP method request * @param array $parameters The request parameters * @param array $files An array of uploaded files * @param array $cookies An array of cookies * @param array $server An array of server parameters * @param string $content The raw body data * * @api */ public function __construct($uri, $method, array $parameters = array(), array $files = array(), array $cookies = array(), array $server = array(), $content = null) { $this->uri = $uri; $this->method = $method; $this->parameters = $parameters; $this->files = $files; $this->cookies = $cookies; $this->server = $server; $this->content = $content; } /** * Gets the request URI. * * @return string The request URI * * @api */ public function getUri() { return $this->uri; } /** * Gets the request HTTP method. * * @return string The request HTTP method * * @api */ public function getMethod() { return $this->method; } /** * Gets the request parameters. * * @return array The request parameters * * @api */ public function getParameters() { return $this->parameters; } /** * Gets the request server files. * * @return array The request files * * @api */ public function getFiles() { return $this->files; } /** * Gets the request cookies. * * @return array The request cookies * * @api */ public function getCookies() { return $this->cookies; } /** * Gets the request server parameters. * * @return array The request server parameters * * @api */ public function getServer() { return $this->server; } /** * Gets the request raw body data. * * @return string The request raw body data. * * @api */ public function getContent() { return $this->content; } } PK]9;""BrowserKit/Cookie.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; /** * Cookie represents an HTTP cookie. * * @author Fabien Potencier * * @api */ class Cookie { /** * Handles dates as defined by RFC 2616 section 3.3.1, and also some other * non-standard, but common formats. * * @var array */ private static $dateFormats = array( 'D, d M Y H:i:s T', 'D, d-M-y H:i:s T', 'D, d-M-Y H:i:s T', 'D, d-m-y H:i:s T', 'D, d-m-Y H:i:s T', 'D M j G:i:s Y', 'D M d H:i:s Y T', ); protected $name; protected $value; protected $expires; protected $path; protected $domain; protected $secure; protected $httponly; protected $rawValue; /** * Sets a cookie. * * @param string $name The cookie name * @param string $value The value of the cookie * @param string $expires The time the cookie expires * @param string $path The path on the server in which the cookie will be available on * @param string $domain The domain that the cookie is available * @param Boolean $secure Indicates that the cookie should only be transmitted over a secure HTTPS connection from the client * @param Boolean $httponly The cookie httponly flag * @param Boolean $encodedValue Whether the value is encoded or not * * @api */ public function __construct($name, $value, $expires = null, $path = null, $domain = '', $secure = false, $httponly = true, $encodedValue = false) { if ($encodedValue) { $this->value = urldecode($value); $this->rawValue = $value; } else { $this->value = $value; $this->rawValue = urlencode($value); } $this->name = $name; $this->expires = null === $expires ? null : (integer) $expires; $this->path = empty($path) ? '/' : $path; $this->domain = $domain; $this->secure = (Boolean) $secure; $this->httponly = (Boolean) $httponly; } /** * Returns the HTTP representation of the Cookie. * * @return string The HTTP representation of the Cookie * * @throws \UnexpectedValueException * * @api */ public function __toString() { $cookie = sprintf('%s=%s', $this->name, $this->rawValue); if (null !== $this->expires) { $dateTime = \DateTime::createFromFormat('U', $this->expires, new \DateTimeZone('GMT')); if ($dateTime === false) { throw new \UnexpectedValueException(sprintf('The cookie expiration time "%s" is not valid.'), $this->expires); } $cookie .= '; expires='.str_replace('+0000', '', $dateTime->format(self::$dateFormats[0])); } if ('' !== $this->domain) { $cookie .= '; domain='.$this->domain; } if ($this->path) { $cookie .= '; path='.$this->path; } if ($this->secure) { $cookie .= '; secure'; } if ($this->httponly) { $cookie .= '; httponly'; } return $cookie; } /** * Creates a Cookie instance from a Set-Cookie header value. * * @param string $cookie A Set-Cookie header value * @param string $url The base URL * * @return Cookie A Cookie instance * * @throws \InvalidArgumentException * * @api */ public static function fromString($cookie, $url = null) { $parts = explode(';', $cookie); if (false === strpos($parts[0], '=')) { throw new \InvalidArgumentException(sprintf('The cookie string "%s" is not valid.', $parts[0])); } list($name, $value) = explode('=', array_shift($parts), 2); $values = array( 'name' => trim($name), 'value' => trim($value), 'expires' => null, 'path' => '/', 'domain' => '', 'secure' => false, 'httponly' => false, 'passedRawValue' => true, ); if (null !== $url) { if ((false === $urlParts = parse_url($url)) || !isset($urlParts['host']) || !isset($urlParts['path'])) { throw new \InvalidArgumentException(sprintf('The URL "%s" is not valid.', $url)); } $values['domain'] = $urlParts['host']; $values['path'] = substr($urlParts['path'], 0, strrpos($urlParts['path'], '/')); } foreach ($parts as $part) { $part = trim($part); if ('secure' === strtolower($part)) { // Ignore the secure flag if the original URI is not given or is not HTTPS if (!$url || !isset($urlParts['scheme']) || 'https' != $urlParts['scheme']) { continue; } $values['secure'] = true; continue; } if ('httponly' === strtolower($part)) { $values['httponly'] = true; continue; } if (2 === count($elements = explode('=', $part, 2))) { if ('expires' === strtolower($elements[0])) { $elements[1] = self::parseDate($elements[1]); } $values[strtolower($elements[0])] = $elements[1]; } } return new static( $values['name'], $values['value'], $values['expires'], $values['path'], $values['domain'], $values['secure'], $values['httponly'], $values['passedRawValue'] ); } private static function parseDate($dateValue) { // trim single quotes around date if present if (($length = strlen($dateValue)) > 1 && "'" === $dateValue[0] && "'" === $dateValue[$length-1]) { $dateValue = substr($dateValue, 1, -1); } foreach (self::$dateFormats as $dateFormat) { if (false !== $date = \DateTime::createFromFormat($dateFormat, $dateValue, new \DateTimeZone('GMT'))) { return $date->getTimestamp(); } } // attempt a fallback for unusual formatting if (false !== $date = date_create($dateValue, new \DateTimeZone('GMT'))) { return $date->getTimestamp(); } throw new \InvalidArgumentException(sprintf('Could not parse date "%s".', $dateValue)); } /** * Gets the name of the cookie. * * @return string The cookie name * * @api */ public function getName() { return $this->name; } /** * Gets the value of the cookie. * * @return string The cookie value * * @api */ public function getValue() { return $this->value; } /** * Gets the raw value of the cookie. * * @return string The cookie value * * @api */ public function getRawValue() { return $this->rawValue; } /** * Gets the expires time of the cookie. * * @return string The cookie expires time * * @api */ public function getExpiresTime() { return $this->expires; } /** * Gets the path of the cookie. * * @return string The cookie path * * @api */ public function getPath() { return $this->path; } /** * Gets the domain of the cookie. * * @return string The cookie domain * * @api */ public function getDomain() { return $this->domain; } /** * Returns the secure flag of the cookie. * * @return Boolean The cookie secure flag * * @api */ public function isSecure() { return $this->secure; } /** * Returns the httponly flag of the cookie. * * @return Boolean The cookie httponly flag * * @api */ public function isHttpOnly() { return $this->httponly; } /** * Returns true if the cookie has expired. * * @return Boolean true if the cookie has expired, false otherwise * * @api */ public function isExpired() { return null !== $this->expires && 0 !== $this->expires && $this->expires < time(); } } PK]/  BrowserKit/History.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; /** * History. * * @author Fabien Potencier */ class History { protected $stack = array(); protected $position = -1; /** * Clears the history. */ public function clear() { $this->stack = array(); $this->position = -1; } /** * Adds a Request to the history. * * @param Request $request A Request instance */ public function add(Request $request) { $this->stack = array_slice($this->stack, 0, $this->position + 1); $this->stack[] = clone $request; $this->position = count($this->stack) - 1; } /** * Returns true if the history is empty. * * @return Boolean true if the history is empty, false otherwise */ public function isEmpty() { return count($this->stack) == 0; } /** * Goes back in the history. * * @return Request A Request instance * * @throws \LogicException if the stack is already on the first page */ public function back() { if ($this->position < 1) { throw new \LogicException('You are already on the first page.'); } return clone $this->stack[--$this->position]; } /** * Goes forward in the history. * * @return Request A Request instance * * @throws \LogicException if the stack is already on the last page */ public function forward() { if ($this->position > count($this->stack) - 2) { throw new \LogicException('You are already on the last page.'); } return clone $this->stack[++$this->position]; } /** * Returns the current element in the history. * * @return Request A Request instance * * @throws \LogicException if the stack is empty */ public function current() { if (-1 == $this->position) { throw new \LogicException('The page history is empty.'); } return clone $this->stack[$this->position]; } } PK]㩑eCCBrowserKit/Client.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\DomCrawler\Link; use Symfony\Component\DomCrawler\Form; use Symfony\Component\Process\PhpProcess; /** * Client simulates a browser. * * To make the actual request, you need to implement the doRequest() method. * * If you want to be able to run requests in their own process (insulated flag), * you need to also implement the getScript() method. * * @author Fabien Potencier * * @api */ abstract class Client { protected $history; protected $cookieJar; protected $server = array(); protected $internalRequest; protected $request; protected $internalResponse; protected $response; protected $crawler; protected $insulated = false; protected $redirect; protected $followRedirects = true; private $maxRedirects = -1; private $redirectCount = 0; private $isMainRequest = true; /** * Constructor. * * @param array $server The server parameters (equivalent of $_SERVER) * @param History $history A History instance to store the browser history * @param CookieJar $cookieJar A CookieJar instance to store the cookies * * @api */ public function __construct(array $server = array(), History $history = null, CookieJar $cookieJar = null) { $this->setServerParameters($server); $this->history = $history ?: new History(); $this->cookieJar = $cookieJar ?: new CookieJar(); } /** * Sets whether to automatically follow redirects or not. * * @param Boolean $followRedirect Whether to follow redirects * * @api */ public function followRedirects($followRedirect = true) { $this->followRedirects = (Boolean) $followRedirect; } /** * Sets the maximum number of requests that crawler can follow. * * @param integer $maxRedirects */ public function setMaxRedirects($maxRedirects) { $this->maxRedirects = $maxRedirects < 0 ? -1 : $maxRedirects; $this->followRedirects = -1 != $this->maxRedirects; } /** * Sets the insulated flag. * * @param Boolean $insulated Whether to insulate the requests or not * * @throws \RuntimeException When Symfony Process Component is not installed * * @api */ public function insulate($insulated = true) { if ($insulated && !class_exists('Symfony\\Component\\Process\\Process')) { // @codeCoverageIgnoreStart throw new \RuntimeException('Unable to isolate requests as the Symfony Process Component is not installed.'); // @codeCoverageIgnoreEnd } $this->insulated = (Boolean) $insulated; } /** * Sets server parameters. * * @param array $server An array of server parameters * * @api */ public function setServerParameters(array $server) { $this->server = array_merge(array( 'HTTP_HOST' => 'localhost', 'HTTP_USER_AGENT' => 'Symfony2 BrowserKit', ), $server); } /** * Sets single server parameter. * * @param string $key A key of the parameter * @param string $value A value of the parameter */ public function setServerParameter($key, $value) { $this->server[$key] = $value; } /** * Gets single server parameter for specified key. * * @param string $key A key of the parameter to get * @param string $default A default value when key is undefined * * @return string A value of the parameter */ public function getServerParameter($key, $default = '') { return (isset($this->server[$key])) ? $this->server[$key] : $default; } /** * Returns the History instance. * * @return History A History instance * * @api */ public function getHistory() { return $this->history; } /** * Returns the CookieJar instance. * * @return CookieJar A CookieJar instance * * @api */ public function getCookieJar() { return $this->cookieJar; } /** * Returns the current Crawler instance. * * @return Crawler|null A Crawler instance * * @api */ public function getCrawler() { return $this->crawler; } /** * Returns the current BrowserKit Response instance. * * @return Response|null A BrowserKit Response instance * * @api */ public function getInternalResponse() { return $this->internalResponse; } /** * Returns the current origin response instance. * * The origin response is the response instance that is returned * by the code that handles requests. * * @return object|null A response instance * * @see doRequest * * @api */ public function getResponse() { return $this->response; } /** * Returns the current BrowserKit Request instance. * * @return Request|null A BrowserKit Request instance * * @api */ public function getInternalRequest() { return $this->internalRequest; } /** * Returns the current origin Request instance. * * The origin request is the request instance that is sent * to the code that handles requests. * * @return object|null A Request instance * * @see doRequest * * @api */ public function getRequest() { return $this->request; } /** * Clicks on a given link. * * @param Link $link A Link instance * * @return Crawler * * @api */ public function click(Link $link) { if ($link instanceof Form) { return $this->submit($link); } return $this->request($link->getMethod(), $link->getUri()); } /** * Submits a form. * * @param Form $form A Form instance * @param array $values An array of form field values * * @return Crawler * * @api */ public function submit(Form $form, array $values = array()) { $form->setValues($values); return $this->request($form->getMethod(), $form->getUri(), $form->getPhpValues(), $form->getPhpFiles()); } /** * Calls a URI. * * @param string $method The request method * @param string $uri The URI to fetch * @param array $parameters The Request parameters * @param array $files The files * @param array $server The server parameters (HTTP headers are referenced with a HTTP_ prefix as PHP does) * @param string $content The raw body data * @param Boolean $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload()) * * @return Crawler * * @api */ public function request($method, $uri, array $parameters = array(), array $files = array(), array $server = array(), $content = null, $changeHistory = true) { if ($this->isMainRequest) { $this->redirectCount = 0; } else { ++$this->redirectCount; } $uri = $this->getAbsoluteUri($uri); if (isset($server['HTTP_HOST'])) { $uri = preg_replace('{^(https?\://)'.parse_url($uri, PHP_URL_HOST).'}', '\\1'.$server['HTTP_HOST'], $uri); } if (isset($server['HTTPS'])) { $uri = preg_replace('{^'.parse_url($uri, PHP_URL_SCHEME).'}', $server['HTTPS'] ? 'https' : 'http', $uri); } $server = array_merge($this->server, $server); if (!$this->history->isEmpty()) { $server['HTTP_REFERER'] = $this->history->current()->getUri(); } $server['HTTP_HOST'] = parse_url($uri, PHP_URL_HOST); if ($port = parse_url($uri, PHP_URL_PORT)) { $server['HTTP_HOST'] .= ':'.$port; } $server['HTTPS'] = 'https' == parse_url($uri, PHP_URL_SCHEME); $this->internalRequest = new Request($uri, $method, $parameters, $files, $this->cookieJar->allValues($uri), $server, $content); $this->request = $this->filterRequest($this->internalRequest); if (true === $changeHistory) { $this->history->add($this->internalRequest); } if ($this->insulated) { $this->response = $this->doRequestInProcess($this->request); } else { $this->response = $this->doRequest($this->request); } $this->internalResponse = $this->filterResponse($this->response); $this->cookieJar->updateFromResponse($this->internalResponse, $uri); $status = $this->internalResponse->getStatus(); if ($status >= 300 && $status < 400) { $this->redirect = $this->internalResponse->getHeader('Location'); } else { $this->redirect = null; } if ($this->followRedirects && $this->redirect) { return $this->crawler = $this->followRedirect(); } return $this->crawler = $this->createCrawlerFromContent($this->internalRequest->getUri(), $this->internalResponse->getContent(), $this->internalResponse->getHeader('Content-Type')); } /** * Makes a request in another process. * * @param object $request An origin request instance * * @return object An origin response instance * * @throws \RuntimeException When processing returns exit code */ protected function doRequestInProcess($request) { // We set the TMPDIR (for Macs) and TEMP (for Windows), because on these platforms the temp directory changes based on the user. $process = new PhpProcess($this->getScript($request), null, array('TMPDIR' => sys_get_temp_dir(), 'TEMP' => sys_get_temp_dir())); $process->run(); if (!$process->isSuccessful() || !preg_match('/^O\:\d+\:/', $process->getOutput())) { throw new \RuntimeException(sprintf('OUTPUT: %s ERROR OUTPUT: %s', $process->getOutput(), $process->getErrorOutput())); } return unserialize($process->getOutput()); } /** * Makes a request. * * @param object $request An origin request instance * * @return object An origin response instance */ abstract protected function doRequest($request); /** * Returns the script to execute when the request must be insulated. * * @param object $request An origin request instance * * @throws \LogicException When this abstract class is not implemented */ protected function getScript($request) { // @codeCoverageIgnoreStart throw new \LogicException('To insulate requests, you need to override the getScript() method.'); // @codeCoverageIgnoreEnd } /** * Filters the BrowserKit request to the origin one. * * @param Request $request The BrowserKit Request to filter * * @return object An origin request instance */ protected function filterRequest(Request $request) { return $request; } /** * Filters the origin response to the BrowserKit one. * * @param object $response The origin response to filter * * @return Response An BrowserKit Response instance */ protected function filterResponse($response) { return $response; } /** * Creates a crawler. * * This method returns null if the DomCrawler component is not available. * * @param string $uri A URI * @param string $content Content for the crawler to use * @param string $type Content type * * @return Crawler|null */ protected function createCrawlerFromContent($uri, $content, $type) { if (!class_exists('Symfony\Component\DomCrawler\Crawler')) { return null; } $crawler = new Crawler(null, $uri); $crawler->addContent($content, $type); return $crawler; } /** * Goes back in the browser history. * * @return Crawler * * @api */ public function back() { return $this->requestFromRequest($this->history->back(), false); } /** * Goes forward in the browser history. * * @return Crawler * * @api */ public function forward() { return $this->requestFromRequest($this->history->forward(), false); } /** * Reloads the current browser. * * @return Crawler * * @api */ public function reload() { return $this->requestFromRequest($this->history->current(), false); } /** * Follow redirects? * * @return Crawler * * @throws \LogicException If request was not a redirect * * @api */ public function followRedirect() { if (empty($this->redirect)) { throw new \LogicException('The request was not redirected.'); } if (-1 !== $this->maxRedirects) { if ($this->redirectCount > $this->maxRedirects) { throw new \LogicException(sprintf('The maximum number (%d) of redirections was reached.', $this->maxRedirects)); } } $request = $this->internalRequest; if (in_array($this->internalResponse->getStatus(), array(302, 303))) { $method = 'get'; $files = array(); $content = null; } else { $method = $request->getMethod(); $files = $request->getFiles(); $content = $request->getContent(); } if ('get' === strtolower($method)) { // Don't forward parameters for GET request as it should reach the redirection URI $parameters = array(); } else { $parameters = $request->getParameters(); } $server = $request->getServer(); $server = $this->updateServerFromUri($server, $this->redirect); $this->isMainRequest = false; $response = $this->request($method, $this->redirect, $parameters, $files, $server, $content); $this->isMainRequest = true; return $response; } /** * Restarts the client. * * It flushes history and all cookies. * * @api */ public function restart() { $this->cookieJar->clear(); $this->history->clear(); } /** * Takes a URI and converts it to absolute if it is not already absolute. * * @param string $uri A URI * * @return string An absolute URI */ protected function getAbsoluteUri($uri) { // already absolute? if (0 === strpos($uri, 'http')) { return $uri; } if (!$this->history->isEmpty()) { $currentUri = $this->history->current()->getUri(); } else { $currentUri = sprintf('http%s://%s/', isset($this->server['HTTPS']) ? 's' : '', isset($this->server['HTTP_HOST']) ? $this->server['HTTP_HOST'] : 'localhost' ); } // protocol relative URL if (0 === strpos($uri, '//')) { return parse_url($currentUri, PHP_URL_SCHEME).':'.$uri; } // anchor? if (!$uri || '#' == $uri[0]) { return preg_replace('/#.*?$/', '', $currentUri).$uri; } if ('/' !== $uri[0]) { $path = parse_url($currentUri, PHP_URL_PATH); if ('/' !== substr($path, -1)) { $path = substr($path, 0, strrpos($path, '/') + 1); } $uri = $path.$uri; } return preg_replace('#^(.*?//[^/]+)\/.*$#', '$1', $currentUri).$uri; } /** * Makes a request from a Request object directly. * * @param Request $request A Request instance * @param Boolean $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload()) * * @return Crawler */ protected function requestFromRequest(Request $request, $changeHistory = true) { return $this->request($request->getMethod(), $request->getUri(), $request->getParameters(), $request->getFiles(), $request->getServer(), $request->getContent(), $changeHistory); } private function updateServerFromUri($server, $uri) { $server['HTTP_HOST'] = parse_url($uri, PHP_URL_HOST); $scheme = parse_url($uri, PHP_URL_SCHEME); $server['HTTPS'] = null === $scheme ? $server['HTTPS'] : 'https' == $scheme; unset($server['HTTP_IF_NONE_MATCH'], $server['HTTP_IF_MODIFIED_SINCE']); return $server; } } PK]l- - BrowserKit/Response.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; /** * Response object. * * @author Fabien Potencier * * @api */ class Response { protected $content; protected $status; protected $headers; /** * Constructor. * * The headers array is a set of key/value pairs. If a header is present multiple times * then the value is an array of all the values. * * @param string $content The content of the response * @param integer $status The response status code * @param array $headers An array of headers * * @api */ public function __construct($content = '', $status = 200, array $headers = array()) { $this->content = $content; $this->status = $status; $this->headers = $headers; } /** * Converts the response object to string containing all headers and the response content. * * @return string The response with headers and content */ public function __toString() { $headers = ''; foreach ($this->headers as $name => $value) { if (is_string($value)) { $headers .= $this->buildHeader($name, $value); } else { foreach ($value as $headerValue) { $headers .= $this->buildHeader($name, $headerValue); } } } return $headers."\n".$this->content; } /** * Returns the build header line. * * @param string $name The header name * @param string $value The header value * * @return string The built header line */ protected function buildHeader($name, $value) { return sprintf("%s: %s\n", $name, $value); } /** * Gets the response content. * * @return string The response content * * @api */ public function getContent() { return $this->content; } /** * Gets the response status code. * * @return integer The response status code * * @api */ public function getStatus() { return $this->status; } /** * Gets the response headers. * * @return array The response headers * * @api */ public function getHeaders() { return $this->headers; } /** * Gets a response header. * * @param string $header The header name * @param Boolean $first Whether to return the first value or all header values * * @return string|array The first header value if $first is true, an array of values otherwise */ public function getHeader($header, $first = true) { foreach ($this->headers as $key => $value) { if (str_replace('-', '_', strtolower($key)) == str_replace('-', '_', strtolower($header))) { if ($first) { return is_array($value) ? (count($value) ? $value[0] : '') : $value; } return is_array($value) ? $value : array($value); } } return $first ? null : array(); } } PK]BrowserKit/CookieJar.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; /** * CookieJar. * * @author Fabien Potencier * * @api */ class CookieJar { protected $cookieJar = array(); /** * Sets a cookie. * * @param Cookie $cookie A Cookie instance * * @api */ public function set(Cookie $cookie) { $this->cookieJar[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie; } /** * Gets a cookie by name. * * You should never use an empty domain, but if you do so, * this method returns the first cookie for the given name/path * (this behavior ensures a BC behavior with previous versions of * Symfony). * * @param string $name The cookie name * @param string $path The cookie path * @param string $domain The cookie domain * * @return Cookie|null A Cookie instance or null if the cookie does not exist * * @api */ public function get($name, $path = '/', $domain = null) { $this->flushExpiredCookies(); if (!empty($domain)) { foreach ($this->cookieJar as $cookieDomain => $pathCookies) { if ($cookieDomain) { $cookieDomain = '.'.ltrim($cookieDomain, '.'); if ($cookieDomain != substr('.'.$domain, -strlen($cookieDomain))) { continue; } } foreach ($pathCookies as $cookiePath => $namedCookies) { if ($cookiePath != substr($path, 0, strlen($cookiePath))) { continue; } if (isset($namedCookies[$name])) { return $namedCookies[$name]; } } } return null; } // avoid relying on this behavior that is mainly here for BC reasons foreach ($this->cookieJar as $cookies) { if (isset($cookies[$path][$name])) { return $cookies[$path][$name]; } } return null; } /** * Removes a cookie by name. * * You should never use an empty domain, but if you do so, * all cookies for the given name/path expire (this behavior * ensures a BC behavior with previous versions of Symfony). * * @param string $name The cookie name * @param string $path The cookie path * @param string $domain The cookie domain * * @api */ public function expire($name, $path = '/', $domain = null) { if (null === $path) { $path = '/'; } if (empty($domain)) { // an empty domain means any domain // this should never happen but it allows for a better BC $domains = array_keys($this->cookieJar); } else { $domains = array($domain); } foreach ($domains as $domain) { unset($this->cookieJar[$domain][$path][$name]); if (empty($this->cookieJar[$domain][$path])) { unset($this->cookieJar[$domain][$path]); if (empty($this->cookieJar[$domain])) { unset($this->cookieJar[$domain]); } } } } /** * Removes all the cookies from the jar. * * @api */ public function clear() { $this->cookieJar = array(); } /** * Updates the cookie jar from a response Set-Cookie headers. * * @param array $setCookies Set-Cookie headers from an HTTP response * @param string $uri The base URL */ public function updateFromSetCookie(array $setCookies, $uri = null) { $cookies = array(); foreach ($setCookies as $cookie) { foreach (explode(',', $cookie) as $i => $part) { if (0 === $i || preg_match('/^(?P\s*[0-9A-Za-z!#\$%\&\'\*\+\-\.^_`\|~]+)=/', $part)) { $cookies[] = ltrim($part); } else { $cookies[count($cookies) - 1] .= ','.$part; } } } foreach ($cookies as $cookie) { try { $this->set(Cookie::fromString($cookie, $uri)); } catch (\InvalidArgumentException $e) { // invalid cookies are just ignored } } } /** * Updates the cookie jar from a Response object. * * @param Response $response A Response object * @param string $uri The base URL */ public function updateFromResponse(Response $response, $uri = null) { $this->updateFromSetCookie($response->getHeader('Set-Cookie', false), $uri); } /** * Returns not yet expired cookies. * * @return Cookie[] An array of cookies */ public function all() { $this->flushExpiredCookies(); $flattenedCookies = array(); foreach ($this->cookieJar as $path) { foreach ($path as $cookies) { foreach ($cookies as $cookie) { $flattenedCookies[] = $cookie; } } } return $flattenedCookies; } /** * Returns not yet expired cookie values for the given URI. * * @param string $uri A URI * @param Boolean $returnsRawValue Returns raw value or urldecoded value * * @return array An array of cookie values */ public function allValues($uri, $returnsRawValue = false) { $this->flushExpiredCookies(); $parts = array_replace(array('path' => '/'), parse_url($uri)); $cookies = array(); foreach ($this->cookieJar as $domain => $pathCookies) { if ($domain) { $domain = '.'.ltrim($domain, '.'); if ($domain != substr('.'.$parts['host'], -strlen($domain))) { continue; } } foreach ($pathCookies as $path => $namedCookies) { if ($path != substr($parts['path'], 0, strlen($path))) { continue; } foreach ($namedCookies as $cookie) { if ($cookie->isSecure() && 'https' != $parts['scheme']) { continue; } $cookies[$cookie->getName()] = $returnsRawValue ? $cookie->getRawValue() : $cookie->getValue(); } } } return $cookies; } /** * Returns not yet expired raw cookie values for the given URI. * * @param string $uri A URI * * @return array An array of cookie values */ public function allRawValues($uri) { return $this->allValues($uri, true); } /** * Removes all expired cookies. */ public function flushExpiredCookies() { foreach ($this->cookieJar as $domain => $pathCookies) { foreach ($pathCookies as $path => $namedCookies) { foreach ($namedCookies as $name => $cookie) { if ($cookie->isExpired()) { unset($this->cookieJar[$domain][$path][$name]); } } } } } } PK].TTBrowserKit/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * Text descriptor. * * @author Jean-François Simon */ class TextDescriptor extends Descriptor { /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) { $default = sprintf(' (default: %s)', $this->formatDefaultValue($argument->getDefault())); } else { $default = ''; } $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($argument->getName()); $this->writeText(sprintf(" %-${nameWidth}s %s%s", $argument->getName(), str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription()), $default ), $options); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) { $default = sprintf(' (default: %s)', $this->formatDefaultValue($option->getDefault())); } else { $default = ''; } $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($option->getName()); $nameWithShortcutWidth = $nameWidth - strlen($option->getName()) - 2; $this->writeText(sprintf(" %s %-${nameWithShortcutWidth}s%s%s%s", '--'.$option->getName(), $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '', str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $option->getDescription()), $default, $option->isArray() ? ' (multiple values allowed)' : '' ), $options); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { $nameWidth = 0; foreach ($definition->getOptions() as $option) { $nameLength = strlen($option->getName()) + 2; if ($option->getShortcut()) { $nameLength += strlen($option->getShortcut()) + 3; } $nameWidth = max($nameWidth, $nameLength); } foreach ($definition->getArguments() as $argument) { $nameWidth = max($nameWidth, strlen($argument->getName())); } ++$nameWidth; if ($definition->getArguments()) { $this->writeText('Arguments:', $options); $this->writeText("\n"); foreach ($definition->getArguments() as $argument) { $this->describeInputArgument($argument, array_merge($options, array('name_width' => $nameWidth))); $this->writeText("\n"); } } if ($definition->getArguments() && $definition->getOptions()) { $this->writeText("\n"); } if ($definition->getOptions()) { $this->writeText('Options:', $options); $this->writeText("\n"); foreach ($definition->getOptions() as $option) { $this->describeInputOption($option, array_merge($options, array('name_width' => $nameWidth))); $this->writeText("\n"); } } } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $command->getSynopsis(); $command->mergeApplicationDefinition(false); $this->writeText('Usage:', $options); $this->writeText("\n"); $this->writeText(' '.$command->getSynopsis(), $options); $this->writeText("\n"); if (count($command->getAliases()) > 0) { $this->writeText("\n"); $this->writeText('Aliases: '.implode(', ', $command->getAliases()).'', $options); } if ($definition = $command->getNativeDefinition()) { $this->writeText("\n"); $this->describeInputDefinition($definition, $options); } $this->writeText("\n"); if ($help = $command->getProcessedHelp()) { $this->writeText('Help:', $options); $this->writeText("\n"); $this->writeText(' '.str_replace("\n", "\n ", $help), $options); $this->writeText("\n"); } } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new ApplicationDescription($application, $describedNamespace); if (isset($options['raw_text']) && $options['raw_text']) { $width = $this->getColumnWidth($description->getCommands()); foreach ($description->getCommands() as $command) { $this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options); $this->writeText("\n"); } } else { $width = $this->getColumnWidth($description->getCommands()); $this->writeText($application->getHelp(), $options); $this->writeText("\n\n"); if ($describedNamespace) { $this->writeText(sprintf("Available commands for the \"%s\" namespace:", $describedNamespace), $options); } else { $this->writeText('Available commands:', $options); } // add commands by namespace foreach ($description->getNamespaces() as $namespace) { if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { $this->writeText("\n"); $this->writeText(''.$namespace['id'].'', $options); } foreach ($namespace['commands'] as $name) { $this->writeText("\n"); $this->writeText(sprintf(" %-${width}s %s", $name, $description->getCommand($name)->getDescription()), $options); } } $this->writeText("\n"); } } /** * {@inheritdoc} */ private function writeText($content, array $options = array()) { $this->write( isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, isset($options['raw_output']) ? !$options['raw_output'] : true ); } /** * Formats input option/argument default value. * * @param mixed $default * * @return string */ private function formatDefaultValue($default) { if (version_compare(PHP_VERSION, '5.4', '<')) { return str_replace('\/', '/', json_encode($default)); } return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } /** * @param Command[] $commands * * @return int */ private function getColumnWidth(array $commands) { $width = 0; foreach ($commands as $command) { $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width; } return $width + 2; } } PK]m !Console/Descriptor/Descriptor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * @author Jean-François Simon */ abstract class Descriptor implements DescriptorInterface { /** * @var OutputInterface */ private $output; /** * {@inheritdoc} */ public function describe(OutputInterface $output, $object, array $options = array()) { $this->output = $output; switch (true) { case $object instanceof InputArgument: $this->describeInputArgument($object, $options); break; case $object instanceof InputOption: $this->describeInputOption($object, $options); break; case $object instanceof InputDefinition: $this->describeInputDefinition($object, $options); break; case $object instanceof Command: $this->describeCommand($object, $options); break; case $object instanceof Application: $this->describeApplication($object, $options); break; default: throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object))); } } /** * Writes content to output. * * @param string $content * @param boolean $decorated */ protected function write($content, $decorated = false) { $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); } /** * Describes an InputArgument instance. * * @param InputArgument $argument * @param array $options * * @return string|mixed */ abstract protected function describeInputArgument(InputArgument $argument, array $options = array()); /** * Describes an InputOption instance. * * @param InputOption $option * @param array $options * * @return string|mixed */ abstract protected function describeInputOption(InputOption $option, array $options = array()); /** * Describes an InputDefinition instance. * * @param InputDefinition $definition * @param array $options * * @return string|mixed */ abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array()); /** * Describes a Command instance. * * @param Command $command * @param array $options * * @return string|mixed */ abstract protected function describeCommand(Command $command, array $options = array()); /** * Describes an Application instance. * * @param Application $application * @param array $options * * @return string|mixed */ abstract protected function describeApplication(Application $application, array $options = array()); } PK]sX -Console/Descriptor/ApplicationDescription.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; /** * @author Jean-François Simon */ class ApplicationDescription { const GLOBAL_NAMESPACE = '_global'; /** * @var Application */ private $application; /** * @var null|string */ private $namespace; /** * @var array */ private $namespaces; /** * @var Command[] */ private $commands; /** * @var Command[] */ private $aliases; /** * Constructor. * * @param Application $application * @param string|null $namespace */ public function __construct(Application $application, $namespace = null) { $this->application = $application; $this->namespace = $namespace; } /** * @return array */ public function getNamespaces() { if (null === $this->namespaces) { $this->inspectApplication(); } return $this->namespaces; } /** * @return Command[] */ public function getCommands() { if (null === $this->commands) { $this->inspectApplication(); } return $this->commands; } /** * @param string $name * * @return Command * * @throws \InvalidArgumentException */ public function getCommand($name) { if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { throw new \InvalidArgumentException(sprintf('Command %s does not exist.', $name)); } return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; } private function inspectApplication() { $this->commands = array(); $this->namespaces = array(); $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null); foreach ($this->sortCommands($all) as $namespace => $commands) { $names = array(); /** @var Command $command */ foreach ($commands as $name => $command) { if (!$command->getName()) { continue; } if ($command->getName() === $name) { $this->commands[$name] = $command; } else { $this->aliases[$name] = $command; } $names[] = $name; } $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names); } } /** * @param array $commands * * @return array */ private function sortCommands(array $commands) { $namespacedCommands = array(); foreach ($commands as $name => $command) { $key = $this->application->extractNamespace($name, 1); if (!$key) { $key = '_global'; } $namespacedCommands[$key][$name] = $command; } ksort($namespacedCommands); foreach ($namespacedCommands as &$commands) { ksort($commands); } return $namespacedCommands; } } PK]ﶲ%%$Console/Descriptor/XmlDescriptor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * XML descriptor. * * @author Jean-François Simon */ class XmlDescriptor extends Descriptor { /** * @param InputDefinition $definition * * @return \DOMDocument */ public function getInputDefinitionDocument(InputDefinition $definition) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($definitionXML = $dom->createElement('definition')); $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); foreach ($definition->getArguments() as $argument) { $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument)); } $definitionXML->appendChild($optionsXML = $dom->createElement('options')); foreach ($definition->getOptions() as $option) { $this->appendDocument($optionsXML, $this->getInputOptionDocument($option)); } return $dom; } /** * @param Command $command * * @return \DOMDocument */ public function getCommandDocument(Command $command) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($commandXML = $dom->createElement('command')); $command->getSynopsis(); $command->mergeApplicationDefinition(false); $commandXML->setAttribute('id', $command->getName()); $commandXML->setAttribute('name', $command->getName()); $commandXML->appendChild($usageXML = $dom->createElement('usage')); $usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), ''))); $commandXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); $commandXML->appendChild($helpXML = $dom->createElement('help')); $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); $commandXML->appendChild($aliasesXML = $dom->createElement('aliases')); foreach ($command->getAliases() as $alias) { $aliasesXML->appendChild($aliasXML = $dom->createElement('alias')); $aliasXML->appendChild($dom->createTextNode($alias)); } $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition()); $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); return $dom; } /** * @param Application $application * @param string|null $namespace * * @return \DOMDocument */ public function getApplicationDocument(Application $application, $namespace = null) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($rootXml = $dom->createElement('symfony')); if ($application->getName() !== 'UNKNOWN') { $rootXml->setAttribute('name', $application->getName()); if ($application->getVersion() !== 'UNKNOWN') { $rootXml->setAttribute('version', $application->getVersion()); } } $rootXml->appendChild($commandsXML = $dom->createElement('commands')); $description = new ApplicationDescription($application, $namespace); if ($namespace) { $commandsXML->setAttribute('namespace', $namespace); } foreach ($description->getCommands() as $command) { $this->appendDocument($commandsXML, $this->getCommandDocument($command)); } if (!$namespace) { $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); foreach ($description->getNamespaces() as $namespaceDescription) { $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']); foreach ($namespaceDescription['commands'] as $name) { $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); $commandXML->appendChild($dom->createTextNode($name)); } } } return $dom; } /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { $this->writeDocument($this->getInputArgumentDocument($argument)); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { $this->writeDocument($this->getInputOptionDocument($option)); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { $this->writeDocument($this->getInputDefinitionDocument($definition)); } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $this->writeDocument($this->getCommandDocument($command)); } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null)); } /** * Appends document children to parent node. * * @param \DOMNode $parentNode * @param \DOMNode $importedParent */ private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) { foreach ($importedParent->childNodes as $childNode) { $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); } } /** * Writes DOM document. * * @param \DOMDocument $dom * * @return \DOMDocument|string */ private function writeDocument(\DOMDocument $dom) { $dom->formatOutput = true; $this->write($dom->saveXML()); } /** * @param InputArgument $argument * * @return \DOMDocument */ private function getInputArgumentDocument(InputArgument $argument) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($objectXML = $dom->createElement('argument')); $objectXML->setAttribute('name', $argument->getName()); $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); $objectXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array())); foreach ($defaults as $default) { $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); $defaultXML->appendChild($dom->createTextNode($default)); } return $dom; } /** * @param InputOption $option * * @return \DOMDocument */ private function getInputOptionDocument(InputOption $option) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($objectXML = $dom->createElement('option')); $objectXML->setAttribute('name', '--'.$option->getName()); $pos = strpos($option->getShortcut(), '|'); if (false !== $pos) { $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut()))); } else { $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); } $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); $objectXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); if ($option->acceptValue()) { $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array())); $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); if (!empty($defaults)) { foreach ($defaults as $default) { $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); $defaultXML->appendChild($dom->createTextNode($default)); } } } return $dom; } } PK]lP..)Console/Descriptor/MarkdownDescriptor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * Markdown descriptor. * * @author Jean-François Simon */ class MarkdownDescriptor extends Descriptor { /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { $this->write( '**'.$argument->getName().':**'."\n\n" .'* Name: '.($argument->getName() ?: '')."\n" .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" .'* Description: '.($argument->getDescription() ?: '')."\n" .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' ); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { $this->write( '**'.$option->getName().':**'."\n\n" .'* Name: `--'.$option->getName().'`'."\n" .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '')."\n" .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" .'* Description: '.($option->getDescription() ?: '')."\n" .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' ); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { if ($showArguments = count($definition->getArguments()) > 0) { $this->write('### Arguments:'); foreach ($definition->getArguments() as $argument) { $this->write("\n\n"); $this->write($this->describeInputArgument($argument)); } } if (count($definition->getOptions()) > 0) { if ($showArguments) { $this->write("\n\n"); } $this->write('### Options:'); foreach ($definition->getOptions() as $option) { $this->write("\n\n"); $this->write($this->describeInputOption($option)); } } } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $command->getSynopsis(); $command->mergeApplicationDefinition(false); $this->write( $command->getName()."\n" .str_repeat('-', strlen($command->getName()))."\n\n" .'* Description: '.($command->getDescription() ?: '')."\n" .'* Usage: `'.$command->getSynopsis().'`'."\n" .'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : '') ); if ($help = $command->getProcessedHelp()) { $this->write("\n\n"); $this->write($help); } if ($definition = $command->getNativeDefinition()) { $this->write("\n\n"); $this->describeInputDefinition($command->getNativeDefinition()); } } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new ApplicationDescription($application, $describedNamespace); $this->write($application->getName()."\n".str_repeat('=', strlen($application->getName()))); foreach ($description->getNamespaces() as $namespace) { if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { $this->write("\n\n"); $this->write('**'.$namespace['id'].':**'); } $this->write("\n\n"); $this->write(implode("\n", array_map(function ($commandName) { return '* '.$commandName; } , $namespace['commands']))); } foreach ($description->getCommands() as $command) { $this->write("\n\n"); $this->write($this->describeCommand($command)); } } } PK]Duu%Console/Descriptor/JsonDescriptor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * JSON descriptor. * * @author Jean-François Simon */ class JsonDescriptor extends Descriptor { /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { $this->writeData($this->getInputArgumentData($argument), $options); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { $this->writeData($this->getInputOptionData($option), $options); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { $this->writeData($this->getInputDefinitionData($definition), $options); } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $this->writeData($this->getCommandData($command), $options); } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new ApplicationDescription($application, $describedNamespace); $commands = array(); foreach ($description->getCommands() as $command) { $commands[] = $this->getCommandData($command); } $data = $describedNamespace ? array('commands' => $commands, 'namespace' => $describedNamespace) : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces())); $this->writeData($data, $options); } /** * Writes data as json. * * @param array $data * @param array $options * * @return array|string */ private function writeData(array $data, array $options) { $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0)); } /** * @param InputArgument $argument * * @return array */ private function getInputArgumentData(InputArgument $argument) { return array( 'name' => $argument->getName(), 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), 'description' => $argument->getDescription(), 'default' => $argument->getDefault(), ); } /** * @param InputOption $option * * @return array */ private function getInputOptionData(InputOption $option) { return array( 'name' => '--'.$option->getName(), 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '', 'accept_value' => $option->acceptValue(), 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), 'description' => $option->getDescription(), 'default' => $option->getDefault(), ); } /** * @param InputDefinition $definition * * @return array */ private function getInputDefinitionData(InputDefinition $definition) { $inputArguments = array(); foreach ($definition->getArguments() as $name => $argument) { $inputArguments[$name] = $this->getInputArgumentData($argument); } $inputOptions = array(); foreach ($definition->getOptions() as $name => $option) { $inputOptions[$name] = $this->getInputOptionData($option); } return array('arguments' => $inputArguments, 'options' => $inputOptions); } /** * @param Command $command * * @return array */ private function getCommandData(Command $command) { $command->getSynopsis(); $command->mergeApplicationDefinition(false); return array( 'name' => $command->getName(), 'usage' => $command->getSynopsis(), 'description' => $command->getDescription(), 'help' => $command->getProcessedHelp(), 'aliases' => $command->getAliases(), 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()), ); } } PK]JZ0<*Console/Descriptor/DescriptorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Output\OutputInterface; /** * Descriptor interface. * * @author Jean-François Simon */ interface DescriptorInterface { /** * Describes an InputArgument instance. * * @param OutputInterface $output * @param object $object * @param array $options */ public function describe(OutputInterface $output, $object, array $options = array()); } PK]v$$%Console/Resources/bin/hiddeninput.exenu[MZ@ !L!This program cannot be run in DOS mode. $,;B;B;B2מ:B2-B2ƞ9B2ў?Ba98B;CB2Ȟ:B2֞:B2Ӟ:BRich;BPELMoO  8 @`?@"P@ Pp!8!@ .text   `.rdata @@.data0@.rsrc @@@.relocP"@Bj$@xj @eEPV @EЃPV @MX @eEP5H @L @YY5\ @EP5` @D @YYP @MMT @3H; 0@uh@l3@$40@5h3@40@h$0@h(0@h 0@ @00@}jYjh"@3ۉ]dp]俀3@SVW0 @;t;u3Fuh4 @3F|3@;u j\Y;|3@u,5|3@h @h @YYtE5<0@|3@;uh @h @lYY|3@9]uSW8 @93@th3@Yt SjS3@$0@ @5$0@5(0@5 0@ 80@9,0@u7P @E MPQYYËeE80@39,0@uPh @9<0@u @E80@øMZf9@t3M<@@8PEuH t uՃv39xtv39j,0@p @jl @YY3@3@ @ t3@ @ p3@ @x3@V=0@u h@ @Yg=0@u j @Y3{U(H1@ D1@@1@<1@581@=41@f`1@f T1@f01@f,1@f%(1@f-$1@X1@EL1@EP1@E\1@0@P1@L0@@0@ D0@0@0@ @0@j?Yj @h!@$ @=0@ujYh ( @P, @ËUE8csmu*xu$@= t=!t="t=@u3]hH@ @3% @jh("@b53@5 @YEu u @YgjYe53@։E53@YYEEPEPu5l @YPUEu֣3@uփ3@E EjYËUuNYH]ËV!@!@W;stЃ;r_^ËV"@"@W;stЃ;r_^% @̋UMMZf9t3]ËA<8PEu3ҹ f9H‹]̋UEH<ASVq3WDv} H ;r X;r B(;r3_^[]̋UjhH"@he@dPSVW0@1E3PEdeEh@*tUE-@Ph@Pt;@$ЃEMd Y_^[]ËE3=‹ËeE3Md Y_^[]% @% @he@d5D$l$l$+SVW0@1E3PeuEEEEdËMd Y__^[]QËUuuu uh@h0@]ËVhh3V t VVVVV^3ËU0@eeSWN@;t t У0@`VEP< @u3u @3 @3 @3EP @E3E3;uO@ u 50@։50@^_[%t @%x @%| @% @% @% @% @% @% @Pd5D$ +d$ SVW(0@3PEuEEdËMd Y__^[]QËM3M%T @T$B J3J3l"@s###)r)b)H)4))(((((()#$%%&d&&$('''''(((6('H(Z(t(('''''l'^'R'F'>'>(0'')@W@@MoOl!@0@0@bad allocationH0@!@RSDSьJ!LZc:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdbe@@:@@@@"d"@"# $#&D H#(h ###)r)b)H)4))(((((()#$%%&d&&$('''''(((6('H(Z(t(('''''l'^'R'F'>'>(0'')GetConsoleModeSetConsoleMode;GetStdHandleKERNEL32.dll??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@AJ?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z_??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ{??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@ZMSVCP90.dll_amsg_exit__getmainargs,_cexit|_exitf_XcptFilterexit__initenv_initterm_initterm_e<_configthreadlocale__setusermatherr _adjust_fdiv__p__commode__p__fmodej_encode_pointer__set_app_typeK_crt_debugger_hookC?terminate@@YAXXZMSVCR90.dll_unlock__dllonexitv_lock_onexit`_decode_pointers_except_handler4_common _invoke_watson?_controlfp_sInterlockedExchange!SleepInterlockedCompareExchange-TerminateProcessGetCurrentProcess>UnhandledExceptionFilterSetUnhandledExceptionFilterIsDebuggerPresentTQueryPerformanceCounterfGetTickCountGetCurrentThreadIdGetCurrentProcessIdOGetSystemTimeAsFileTimes__CxxFrameHandler3N@D$!@ 8Ph  @(CV(4VS_VERSION_INFOStringFileInfob040904b0QFileDescriptionReads from stdin without leaking info to the terminal and outputs back to stdout6 FileVersion1, 0, 0, 08 InternalNamehiddeninputPLegalCopyrightJordi Boggiano - 2012HOriginalFilenamehiddeninput.exe: ProductNameHidden Input: ProductVersion1, 0, 0, 0DVarFileInfo$Translation  PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING@00!0/080F0L0T0^0d0n0{000000000000001#1-1@1J1O1T1v1{1111111111111112"2*23292A2M2_2j2p222222222222 333%303N3T3Z3`3f3l3s3z333333333333333334444%4;4B444444444445!5^5c5555H6M6_6}66677 7*7w7|777778 88=8E8P8V8\8b8h8n8t8z88889 $0001 1t1x12 2@2\2`2h2t20 0PK]LUҊҊConsole/Application.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputAwareInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\HelpCommand; use Symfony\Component\Console\Command\ListCommand; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Helper\FormatterHelper; use Symfony\Component\Console\Helper\DialogHelper; use Symfony\Component\Console\Helper\ProgressHelper; use Symfony\Component\Console\Helper\TableHelper; use Symfony\Component\Console\Event\ConsoleCommandEvent; use Symfony\Component\Console\Event\ConsoleExceptionEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * An Application is the container for a collection of commands. * * It is the main entry point of a Console application. * * This class is optimized for a standard CLI environment. * * Usage: * * $app = new Application('myapp', '1.0 (stable)'); * $app->add(new SimpleCommand()); * $app->run(); * * @author Fabien Potencier * * @api */ class Application { private $commands = array(); private $wantHelps = false; private $runningCommand; private $name; private $version; private $catchExceptions = true; private $autoExit = true; private $definition; private $helperSet; private $dispatcher; private $terminalDimensions; /** * Constructor. * * @param string $name The name of the application * @param string $version The version of the application * * @api */ public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') { $this->name = $name; $this->version = $version; $this->helperSet = $this->getDefaultHelperSet(); $this->definition = $this->getDefaultInputDefinition(); foreach ($this->getDefaultCommands() as $command) { $this->add($command); } } public function setDispatcher(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } /** * Runs the current application. * * @param InputInterface $input An Input instance * @param OutputInterface $output An Output instance * * @return integer 0 if everything went fine, or an error code * * @throws \Exception When doRun returns Exception * * @api */ public function run(InputInterface $input = null, OutputInterface $output = null) { if (null === $input) { $input = new ArgvInput(); } if (null === $output) { $output = new ConsoleOutput(); } $this->configureIO($input, $output); try { $exitCode = $this->doRun($input, $output); } catch (\Exception $e) { if (!$this->catchExceptions) { throw $e; } if ($output instanceof ConsoleOutputInterface) { $this->renderException($e, $output->getErrorOutput()); } else { $this->renderException($e, $output); } $exitCode = $e->getCode(); if (is_numeric($exitCode)) { $exitCode = (int) $exitCode; if (0 === $exitCode) { $exitCode = 1; } } else { $exitCode = 1; } } if ($this->autoExit) { if ($exitCode > 255) { $exitCode = 255; } // @codeCoverageIgnoreStart exit($exitCode); // @codeCoverageIgnoreEnd } return $exitCode; } /** * Runs the current application. * * @param InputInterface $input An Input instance * @param OutputInterface $output An Output instance * * @return integer 0 if everything went fine, or an error code */ public function doRun(InputInterface $input, OutputInterface $output) { if (true === $input->hasParameterOption(array('--version', '-V'))) { $output->writeln($this->getLongVersion()); return 0; } $name = $this->getCommandName($input); if (true === $input->hasParameterOption(array('--help', '-h'))) { if (!$name) { $name = 'help'; $input = new ArrayInput(array('command' => 'help')); } else { $this->wantHelps = true; } } if (!$name) { $name = 'list'; $input = new ArrayInput(array('command' => 'list')); } // the command name MUST be the first element of the input $command = $this->find($name); $this->runningCommand = $command; $exitCode = $this->doRunCommand($command, $input, $output); $this->runningCommand = null; return $exitCode; } /** * Set a helper set to be used with the command. * * @param HelperSet $helperSet The helper set * * @api */ public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; } /** * Get the helper set associated with the command. * * @return HelperSet The HelperSet instance associated with this command * * @api */ public function getHelperSet() { return $this->helperSet; } /** * Set an input definition set to be used with this application * * @param InputDefinition $definition The input definition * * @api */ public function setDefinition(InputDefinition $definition) { $this->definition = $definition; } /** * Gets the InputDefinition related to this Application. * * @return InputDefinition The InputDefinition instance */ public function getDefinition() { return $this->definition; } /** * Gets the help message. * * @return string A help message. */ public function getHelp() { $messages = array( $this->getLongVersion(), '', 'Usage:', ' [options] command [arguments]', '', 'Options:', ); foreach ($this->getDefinition()->getOptions() as $option) { $messages[] = sprintf(' %-29s %s %s', '--'.$option->getName().'', $option->getShortcut() ? '-'.$option->getShortcut().'' : ' ', $option->getDescription() ); } return implode(PHP_EOL, $messages); } /** * Sets whether to catch exceptions or not during commands execution. * * @param Boolean $boolean Whether to catch exceptions or not during commands execution * * @api */ public function setCatchExceptions($boolean) { $this->catchExceptions = (Boolean) $boolean; } /** * Sets whether to automatically exit after a command execution or not. * * @param Boolean $boolean Whether to automatically exit after a command execution or not * * @api */ public function setAutoExit($boolean) { $this->autoExit = (Boolean) $boolean; } /** * Gets the name of the application. * * @return string The application name * * @api */ public function getName() { return $this->name; } /** * Sets the application name. * * @param string $name The application name * * @api */ public function setName($name) { $this->name = $name; } /** * Gets the application version. * * @return string The application version * * @api */ public function getVersion() { return $this->version; } /** * Sets the application version. * * @param string $version The application version * * @api */ public function setVersion($version) { $this->version = $version; } /** * Returns the long version of the application. * * @return string The long application version * * @api */ public function getLongVersion() { if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) { return sprintf('%s version %s', $this->getName(), $this->getVersion()); } return 'Console Tool'; } /** * Registers a new command. * * @param string $name The command name * * @return Command The newly created command * * @api */ public function register($name) { return $this->add(new Command($name)); } /** * Adds an array of command objects. * * @param Command[] $commands An array of commands * * @api */ public function addCommands(array $commands) { foreach ($commands as $command) { $this->add($command); } } /** * Adds a command object. * * If a command with the same name already exists, it will be overridden. * * @param Command $command A Command object * * @return Command The registered command * * @api */ public function add(Command $command) { $command->setApplication($this); if (!$command->isEnabled()) { $command->setApplication(null); return; } if (null === $command->getDefinition()) { throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command))); } $this->commands[$command->getName()] = $command; foreach ($command->getAliases() as $alias) { $this->commands[$alias] = $command; } return $command; } /** * Returns a registered command by name or alias. * * @param string $name The command name or alias * * @return Command A Command object * * @throws \InvalidArgumentException When command name given does not exist * * @api */ public function get($name) { if (!isset($this->commands[$name])) { throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name)); } $command = $this->commands[$name]; if ($this->wantHelps) { $this->wantHelps = false; $helpCommand = $this->get('help'); $helpCommand->setCommand($command); return $helpCommand; } return $command; } /** * Returns true if the command exists, false otherwise. * * @param string $name The command name or alias * * @return Boolean true if the command exists, false otherwise * * @api */ public function has($name) { return isset($this->commands[$name]); } /** * Returns an array of all unique namespaces used by currently registered commands. * * It does not returns the global namespace which always exists. * * @return array An array of namespaces */ public function getNamespaces() { $namespaces = array(); foreach ($this->commands as $command) { $namespaces[] = $this->extractNamespace($command->getName()); foreach ($command->getAliases() as $alias) { $namespaces[] = $this->extractNamespace($alias); } } return array_values(array_unique(array_filter($namespaces))); } /** * Finds a registered namespace by a name or an abbreviation. * * @param string $namespace A namespace or abbreviation to search for * * @return string A registered namespace * * @throws \InvalidArgumentException When namespace is incorrect or ambiguous */ public function findNamespace($namespace) { $allNamespaces = $this->getNamespaces(); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace); $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces); if (empty($namespaces)) { $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); if ($alternatives = $this->findAlternatives($namespace, $allNamespaces, array())) { if (1 == count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { $message .= "\n\nDid you mean one of these?\n "; } $message .= implode("\n ", $alternatives); } throw new \InvalidArgumentException($message); } $exact = in_array($namespace, $namespaces, true); if (count($namespaces) > 1 && !$exact) { throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces)))); } return $exact ? $namespace : reset($namespaces); } /** * Finds a command by name or alias. * * Contrary to get, this command tries to find the best * match if you give it an abbreviation of a name or alias. * * @param string $name A command name or a command alias * * @return Command A Command instance * * @throws \InvalidArgumentException When command name is incorrect or ambiguous * * @api */ public function find($name) { $allCommands = array_keys($this->commands); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); $commands = preg_grep('{^'.$expr.'}', $allCommands); if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) { if (false !== $pos = strrpos($name, ':')) { // check if a namespace exists and contains commands $this->findNamespace(substr($name, 0, $pos)); } $message = sprintf('Command "%s" is not defined.', $name); if ($alternatives = $this->findAlternatives($name, $allCommands, array())) { if (1 == count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { $message .= "\n\nDid you mean one of these?\n "; } $message .= implode("\n ", $alternatives); } throw new \InvalidArgumentException($message); } // filter out aliases for commands which are already on the list if (count($commands) > 1) { $commandList = $this->commands; $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) { $commandName = $commandList[$nameOrAlias]->getName(); return $commandName === $nameOrAlias || !in_array($commandName, $commands); }); } $exact = in_array($name, $commands, true); if (count($commands) > 1 && !$exact) { $suggestions = $this->getAbbreviationSuggestions(array_values($commands)); throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions)); } return $this->get($exact ? $name : reset($commands)); } /** * Gets the commands (registered in the given namespace if provided). * * The array keys are the full names and the values the command instances. * * @param string $namespace A namespace name * * @return Command[] An array of Command instances * * @api */ public function all($namespace = null) { if (null === $namespace) { return $this->commands; } $commands = array(); foreach ($this->commands as $name => $command) { if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { $commands[$name] = $command; } } return $commands; } /** * Returns an array of possible abbreviations given a set of names. * * @param array $names An array of names * * @return array An array of abbreviations */ public static function getAbbreviations($names) { $abbrevs = array(); foreach ($names as $name) { for ($len = strlen($name); $len > 0; --$len) { $abbrev = substr($name, 0, $len); $abbrevs[$abbrev][] = $name; } } return $abbrevs; } /** * Returns a text representation of the Application. * * @param string $namespace An optional namespace name * @param boolean $raw Whether to return raw command list * * @return string A string representing the Application * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asText($namespace = null, $raw = false) { $descriptor = new TextDescriptor(); $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw); $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true)); return $output->fetch(); } /** * Returns an XML representation of the Application. * * @param string $namespace An optional namespace name * @param Boolean $asDom Whether to return a DOM or an XML string * * @return string|\DOMDocument An XML string representing the Application * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asXml($namespace = null, $asDom = false) { $descriptor = new XmlDescriptor(); if ($asDom) { return $descriptor->getApplicationDocument($this, $namespace); } $output = new BufferedOutput(); $descriptor->describe($output, $this, array('namespace' => $namespace)); return $output->fetch(); } /** * Renders a caught exception. * * @param \Exception $e An exception instance * @param OutputInterface $output An OutputInterface instance */ public function renderException($e, $output) { $strlen = function ($string) { if (!function_exists('mb_strlen')) { return strlen($string); } if (false === $encoding = mb_detect_encoding($string)) { return strlen($string); } return mb_strlen($string, $encoding); }; do { $title = sprintf(' [%s] ', get_class($e)); $len = $strlen($title); // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : (defined('HHVM_VERSION') ? 1 << 31 : PHP_INT_MAX); $formatter = $output->getFormatter(); $lines = array(); foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) { foreach (str_split($line, $width - 4) as $line) { // pre-format lines to get the right string length $lineLength = $strlen(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4; $lines[] = array($line, $lineLength); $len = max($lineLength, $len); } } $messages = array('', ''); $messages[] = $emptyLine = $formatter->format(sprintf('%s', str_repeat(' ', $len))); $messages[] = $formatter->format(sprintf('%s%s', $title, str_repeat(' ', max(0, $len - $strlen($title))))); foreach ($lines as $line) { $messages[] = $formatter->format(sprintf(' %s %s', $line[0], str_repeat(' ', $len - $line[1]))); } $messages[] = $emptyLine; $messages[] = ''; $messages[] = ''; $output->writeln($messages, OutputInterface::OUTPUT_RAW); if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $output->writeln('Exception trace:'); // exception related properties $trace = $e->getTrace(); array_unshift($trace, array( 'function' => '', 'file' => $e->getFile() != null ? $e->getFile() : 'n/a', 'line' => $e->getLine() != null ? $e->getLine() : 'n/a', 'args' => array(), )); for ($i = 0, $count = count($trace); $i < $count; $i++) { $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; $function = $trace[$i]['function']; $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; $output->writeln(sprintf(' %s%s%s() at %s:%s', $class, $type, $function, $file, $line)); } $output->writeln(""); $output->writeln(""); } } while ($e = $e->getPrevious()); if (null !== $this->runningCommand) { $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName()))); $output->writeln(""); $output->writeln(""); } } /** * Tries to figure out the terminal width in which this application runs * * @return int|null */ protected function getTerminalWidth() { $dimensions = $this->getTerminalDimensions(); return $dimensions[0]; } /** * Tries to figure out the terminal height in which this application runs * * @return int|null */ protected function getTerminalHeight() { $dimensions = $this->getTerminalDimensions(); return $dimensions[1]; } /** * Tries to figure out the terminal dimensions based on the current environment * * @return array Array containing width and height */ public function getTerminalDimensions() { if ($this->terminalDimensions) { return $this->terminalDimensions; } if (defined('PHP_WINDOWS_VERSION_BUILD')) { // extract [w, H] from "wxh (WxH)" if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) { return array((int) $matches[1], (int) $matches[2]); } // extract [w, h] from "wxh" if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) { return array((int) $matches[1], (int) $matches[2]); } } if ($sttyString = $this->getSttyColumns()) { // extract [w, h] from "rows h; columns w;" if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { return array((int) $matches[2], (int) $matches[1]); } // extract [w, h] from "; h rows; w columns" if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { return array((int) $matches[2], (int) $matches[1]); } } return array(null, null); } /** * Sets terminal dimensions. * * Can be useful to force terminal dimensions for functional tests. * * @param integer $width The width * @param integer $height The height * * @return Application The current application */ public function setTerminalDimensions($width, $height) { $this->terminalDimensions = array($width, $height); return $this; } /** * Configures the input and output instances based on the user arguments and options. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance */ protected function configureIO(InputInterface $input, OutputInterface $output) { if (true === $input->hasParameterOption(array('--ansi'))) { $output->setDecorated(true); } elseif (true === $input->hasParameterOption(array('--no-ansi'))) { $output->setDecorated(false); } if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) { $input->setInteractive(false); } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('dialog')) { $inputStream = $this->getHelperSet()->get('dialog')->getInputStream(); if (!@posix_isatty($inputStream)) { $input->setInteractive(false); } } if (true === $input->hasParameterOption(array('--quiet', '-q'))) { $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); } else { if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) { $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) { $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) { $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); } } } /** * Runs the current command. * * If an event dispatcher has been attached to the application, * events are also dispatched during the life-cycle of the command. * * @param Command $command A Command instance * @param InputInterface $input An Input instance * @param OutputInterface $output An Output instance * * @return integer 0 if everything went fine, or an error code */ protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) { foreach ($command->getHelperSet() as $helper) { if ($helper instanceof InputAwareInterface) { $helper->setInput($input); } } if (null === $this->dispatcher) { return $command->run($input, $output); } $event = new ConsoleCommandEvent($command, $input, $output); $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event); try { $exitCode = $command->run($input, $output); } catch (\Exception $e) { $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode()); $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); $event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode()); $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); throw $event->getException(); } $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); return $event->getExitCode(); } /** * Gets the name of the command based on input. * * @param InputInterface $input The input interface * * @return string The command name */ protected function getCommandName(InputInterface $input) { return $input->getFirstArgument(); } /** * Gets the default input definition. * * @return InputDefinition An InputDefinition instance */ protected function getDefaultInputDefinition() { return new InputDefinition(array( new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message.'), new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message.'), new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version.'), new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output.'), new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output.'), new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question.'), )); } /** * Gets the default commands that should always be available. * * @return Command[] An array of default Command instances */ protected function getDefaultCommands() { return array(new HelpCommand(), new ListCommand()); } /** * Gets the default helper set with the helpers that should always be available. * * @return HelperSet A HelperSet instance */ protected function getDefaultHelperSet() { return new HelperSet(array( new FormatterHelper(), new DialogHelper(), new ProgressHelper(), new TableHelper(), )); } /** * Runs and parses stty -a if it's available, suppressing any error output * * @return string */ private function getSttyColumns() { if (!function_exists('proc_open')) { return; } $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); if (is_resource($process)) { $info = stream_get_contents($pipes[1]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); return $info; } } /** * Runs and parses mode CON if it's available, suppressing any error output * * @return string x or null if it could not be parsed */ private function getConsoleMode() { if (!function_exists('proc_open')) { return; } $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); if (is_resource($process)) { $info = stream_get_contents($pipes[1]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { return $matches[2].'x'.$matches[1]; } } } /** * Returns abbreviated suggestions in string format. * * @param array $abbrevs Abbreviated suggestions to convert * * @return string A formatted string of abbreviated suggestions */ private function getAbbreviationSuggestions($abbrevs) { return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : ''); } /** * Returns the namespace part of the command name. * * This method is not part of public API and should not be used directly. * * @param string $name The full name of the command * @param string $limit The maximum number of parts of the namespace * * @return string The namespace of the command */ public function extractNamespace($name, $limit = null) { $parts = explode(':', $name); array_pop($parts); return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit)); } /** * Finds alternative of $name among $collection, * if nothing is found in $collection, try in $abbrevs * * @param string $name The string * @param array|\Traversable $collection The collection * * @return array A sorted array of similar string */ private function findAlternatives($name, $collection) { $threshold = 1e3; $alternatives = array(); $collectionParts = array(); foreach ($collection as $item) { $collectionParts[$item] = explode(':', $item); } foreach (explode(':', $name) as $i => $subname) { foreach ($collectionParts as $collectionName => $parts) { $exists = isset($alternatives[$collectionName]); if (!isset($parts[$i]) && $exists) { $alternatives[$collectionName] += $threshold; continue; } elseif (!isset($parts[$i])) { continue; } $lev = levenshtein($subname, $parts[$i]); if ($lev <= strlen($subname) / 3 || false !== strpos($parts[$i], $subname)) { $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; } elseif ($exists) { $alternatives[$collectionName] += $threshold; } } } foreach ($collection as $item) { $lev = levenshtein($name, $item); if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; } } $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2*$threshold; }); asort($alternatives); return array_keys($alternatives); } } PK]2VConsole/Shell.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console; use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Process\ProcessBuilder; use Symfony\Component\Process\PhpExecutableFinder; /** * A Shell wraps an Application to add shell capabilities to it. * * Support for history and completion only works with a PHP compiled * with readline support (either --with-readline or --with-libedit) * * @author Fabien Potencier * @author Martin Hasoň */ class Shell { private $application; private $history; private $output; private $hasReadline; private $processIsolation = false; /** * Constructor. * * If there is no readline support for the current PHP executable * a \RuntimeException exception is thrown. * * @param Application $application An application instance */ public function __construct(Application $application) { $this->hasReadline = function_exists('readline'); $this->application = $application; $this->history = getenv('HOME').'/.history_'.$application->getName(); $this->output = new ConsoleOutput(); } /** * Runs the shell. */ public function run() { $this->application->setAutoExit(false); $this->application->setCatchExceptions(true); if ($this->hasReadline) { readline_read_history($this->history); readline_completion_function(array($this, 'autocompleter')); } $this->output->writeln($this->getHeader()); $php = null; if ($this->processIsolation) { $finder = new PhpExecutableFinder(); $php = $finder->find(); $this->output->writeln(<<Running with process isolation, you should consider this: * each command is executed as separate process, * commands don't support interactivity, all params must be passed explicitly, * commands output is not colorized. EOF ); } while (true) { $command = $this->readline(); if (false === $command) { $this->output->writeln("\n"); break; } if ($this->hasReadline) { readline_add_history($command); readline_write_history($this->history); } if ($this->processIsolation) { $pb = new ProcessBuilder(); $process = $pb ->add($php) ->add($_SERVER['argv'][0]) ->add($command) ->inheritEnvironmentVariables(true) ->getProcess() ; $output = $this->output; $process->run(function ($type, $data) use ($output) { $output->writeln($data); }); $ret = $process->getExitCode(); } else { $ret = $this->application->run(new StringInput($command), $this->output); } if (0 !== $ret) { $this->output->writeln(sprintf('The command terminated with an error status (%s)', $ret)); } } } /** * Returns the shell header. * * @return string The header string */ protected function getHeader() { return <<{$this->application->getName()} shell ({$this->application->getVersion()}). At the prompt, type help for some help, or list to get a list of available commands. To exit the shell, type ^D. EOF; } /** * Renders a prompt. * * @return string The prompt */ protected function getPrompt() { // using the formatter here is required when using readline return $this->output->getFormatter()->format($this->application->getName().' > '); } protected function getOutput() { return $this->output; } protected function getApplication() { return $this->application; } /** * Tries to return autocompletion for the current entered text. * * @param string $text The last segment of the entered text * * @return Boolean|array A list of guessed strings or true */ private function autocompleter($text) { $info = readline_info(); $text = substr($info['line_buffer'], 0, $info['end']); if ($info['point'] !== $info['end']) { return true; } // task name? if (false === strpos($text, ' ') || !$text) { return array_keys($this->application->all()); } // options and arguments? try { $command = $this->application->find(substr($text, 0, strpos($text, ' '))); } catch (\Exception $e) { return true; } $list = array('--help'); foreach ($command->getDefinition()->getOptions() as $option) { $list[] = '--'.$option->getName(); } return $list; } /** * Reads a single line from standard input. * * @return string The single line from standard input */ private function readline() { if ($this->hasReadline) { $line = readline($this->getPrompt()); } else { $this->output->write($this->getPrompt()); $line = fgets(STDIN, 1024); $line = (!$line && strlen($line) == 0) ? false : rtrim($line); } return $line; } public function getProcessIsolation() { return $this->processIsolation; } public function setProcessIsolation($processIsolation) { $this->processIsolation = (Boolean) $processIsolation; if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) { throw new \RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.'); } } } PK]Z\Console/Helper/Helper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * Helper is the base class for all helper classes. * * @author Fabien Potencier */ abstract class Helper implements HelperInterface { protected $helperSet = null; /** * Sets the helper set associated with this helper. * * @param HelperSet $helperSet A HelperSet instance */ public function setHelperSet(HelperSet $helperSet = null) { $this->helperSet = $helperSet; } /** * Gets the helper set associated with this helper. * * @return HelperSet A HelperSet instance */ public function getHelperSet() { return $this->helperSet; } /** * Returns the length of a string, using mb_strlen if it is available. * * @param string $string The string to check its length * * @return integer The length of the string */ protected function strlen($string) { if (!function_exists('mb_strlen')) { return strlen($string); } if (false === $encoding = mb_detect_encoding($string)) { return strlen($string); } return mb_strlen($string, $encoding); } } PK]"U1  #Console/Helper/DescriptorHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Descriptor\DescriptorInterface; use Symfony\Component\Console\Descriptor\JsonDescriptor; use Symfony\Component\Console\Descriptor\MarkdownDescriptor; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Output\OutputInterface; /** * This class adds helper method to describe objects in various formats. * * @author Jean-François Simon */ class DescriptorHelper extends Helper { /** * @var DescriptorInterface[] */ private $descriptors = array(); /** * Constructor. */ public function __construct() { $this ->register('txt', new TextDescriptor()) ->register('xml', new XmlDescriptor()) ->register('json', new JsonDescriptor()) ->register('md', new MarkdownDescriptor()) ; } /** * Describes an object if supported. * * Available options are: * * format: string, the output format name * * raw_text: boolean, sets output type as raw * * @param OutputInterface $output * @param object $object * @param array $options * * @throws \InvalidArgumentException */ public function describe(OutputInterface $output, $object, array $options = array()) { $options = array_merge(array( 'raw_text' => false, 'format' => 'txt', ), $options); if (!isset($this->descriptors[$options['format']])) { throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); } $descriptor = $this->descriptors[$options['format']]; $descriptor->describe($output, $object, $options); } /** * Registers a descriptor. * * @param string $format * @param DescriptorInterface $descriptor * * @return DescriptorHelper */ public function register($format, DescriptorInterface $descriptor) { $this->descriptors[$format] = $descriptor; return $this; } /** * {@inheritdoc} */ public function getName() { return 'descriptor'; } } PK] Console/Helper/HelperSet.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Command\Command; /** * HelperSet represents a set of helpers to be used with a command. * * @author Fabien Potencier */ class HelperSet implements \IteratorAggregate { private $helpers = array(); private $command; /** * Constructor. * * @param Helper[] $helpers An array of helper. */ public function __construct(array $helpers = array()) { foreach ($helpers as $alias => $helper) { $this->set($helper, is_int($alias) ? null : $alias); } } /** * Sets a helper. * * @param HelperInterface $helper The helper instance * @param string $alias An alias */ public function set(HelperInterface $helper, $alias = null) { $this->helpers[$helper->getName()] = $helper; if (null !== $alias) { $this->helpers[$alias] = $helper; } $helper->setHelperSet($this); } /** * Returns true if the helper if defined. * * @param string $name The helper name * * @return Boolean true if the helper is defined, false otherwise */ public function has($name) { return isset($this->helpers[$name]); } /** * Gets a helper value. * * @param string $name The helper name * * @return HelperInterface The helper instance * * @throws \InvalidArgumentException if the helper is not defined */ public function get($name) { if (!$this->has($name)) { throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); } return $this->helpers[$name]; } /** * Sets the command associated with this helper set. * * @param Command $command A Command instance */ public function setCommand(Command $command = null) { $this->command = $command; } /** * Gets the command associated with this helper set. * * @return Command A Command instance */ public function getCommand() { return $this->command; } public function getIterator() { return new \ArrayIterator($this->helpers); } } PK]gse"Console/Helper/FormatterHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Formatter\OutputFormatter; /** * The Formatter class provides helpers to format messages. * * @author Fabien Potencier */ class FormatterHelper extends Helper { /** * Formats a message within a section. * * @param string $section The section name * @param string $message The message * @param string $style The style to apply to the section * * @return string The format section */ public function formatSection($section, $message, $style = 'info') { return sprintf('<%s>[%s] %s', $style, $section, $style, $message); } /** * Formats a message as a block of text. * * @param string|array $messages The message to write in the block * @param string $style The style to apply to the whole block * @param Boolean $large Whether to return a large block * * @return string The formatter message */ public function formatBlock($messages, $style, $large = false) { $messages = (array) $messages; $len = 0; $lines = array(); foreach ($messages as $message) { $message = OutputFormatter::escape($message); $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); $len = max($this->strlen($message) + ($large ? 4 : 2), $len); } $messages = $large ? array(str_repeat(' ', $len)) : array(); foreach ($lines as $line) { $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); } if ($large) { $messages[] = str_repeat(' ', $len); } foreach ($messages as &$message) { $message = sprintf('<%s>%s', $style, $message, $style); } return implode("\n", $messages); } /** * {@inheritDoc} */ public function getName() { return 'formatter'; } } PK]&>@>@Console/Helper/DialogHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Formatter\OutputFormatterStyle; /** * The Dialog class provides helpers to interact with the user. * * @author Fabien Potencier */ class DialogHelper extends InputAwareHelper { private $inputStream; private static $shell; private static $stty; /** * Asks the user to select a value. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param array $choices List of choices to pick from * @param Boolean|string $default The default answer if the user enters nothing * @param Boolean|integer $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param string $errorMessage Message which will be shown if invalid value from choice list would be picked * @param Boolean $multiselect Select more than one value separated by comma * * @return integer|string|array The selected value or values (the key of the choices array) * * @throws \InvalidArgumentException */ public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false) { $width = max(array_map('strlen', array_keys($choices))); $messages = (array) $question; foreach ($choices as $key => $value) { $messages[] = sprintf(" [%-${width}s] %s", $key, $value); } $output->writeln($messages); $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) { // Collapse all spaces. $selectedChoices = str_replace(" ", "", $picked); if ($multiselect) { // Check for a separated comma values if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) { throw new \InvalidArgumentException(sprintf($errorMessage, $picked)); } $selectedChoices = explode(",", $selectedChoices); } else { $selectedChoices = array($picked); } $multiselectChoices = array(); foreach ($selectedChoices as $value) { if (empty($choices[$value])) { throw new \InvalidArgumentException(sprintf($errorMessage, $value)); } array_push($multiselectChoices, $value); } if ($multiselect) { return $multiselectChoices; } return $picked; }, $attempts, $default); return $result; } /** * Asks a question to the user. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param string $default The default answer if none is given by the user * @param array $autocomplete List of values to autocomplete * * @return string The user answer * * @throws \RuntimeException If there is no data to read in the input stream */ public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null) { if ($this->input && !$this->input->isInteractive()) { return $default; } $output->write($question); $inputStream = $this->inputStream ?: STDIN; if (null === $autocomplete || !$this->hasSttyAvailable()) { $ret = fgets($inputStream, 4096); if (false === $ret) { throw new \RuntimeException('Aborted'); } $ret = trim($ret); } else { $ret = ''; $i = 0; $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); $sttyMode = shell_exec('stty -g'); // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) shell_exec('stty -icanon -echo'); // Add highlighted text style $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); // Read a keypress while (!feof($inputStream)) { $c = fread($inputStream, 1); // Backspace Character if ("\177" === $c) { if (0 === $numMatches && 0 !== $i) { $i--; // Move cursor backwards $output->write("\033[1D"); } if ($i === 0) { $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); } else { $numMatches = 0; } // Pop the last character off the end of our string $ret = substr($ret, 0, $i); } elseif ("\033" === $c) { // Did we read an escape sequence? $c .= fread($inputStream, 2); // A = Up Arrow. B = Down Arrow if ('A' === $c[2] || 'B' === $c[2]) { if ('A' === $c[2] && -1 === $ofs) { $ofs = 0; } if (0 === $numMatches) { continue; } $ofs += ('A' === $c[2]) ? -1 : 1; $ofs = ($numMatches + $ofs) % $numMatches; } } elseif (ord($c) < 32) { if ("\t" === $c || "\n" === $c) { if ($numMatches > 0 && -1 !== $ofs) { $ret = $matches[$ofs]; // Echo out remaining chars for current match $output->write(substr($ret, $i)); $i = strlen($ret); } if ("\n" === $c) { $output->write($c); break; } $numMatches = 0; } continue; } else { $output->write($c); $ret .= $c; $i++; $numMatches = 0; $ofs = 0; foreach ($autocomplete as $value) { // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) if (0 === strpos($value, $ret) && $i !== strlen($value)) { $matches[$numMatches++] = $value; } } } // Erase characters from cursor to end of line $output->write("\033[K"); if ($numMatches > 0 && -1 !== $ofs) { // Save cursor position $output->write("\0337"); // Write highlighted text $output->write(''.substr($matches[$ofs], $i).''); // Restore cursor position $output->write("\0338"); } } // Reset stty so it behaves normally again shell_exec(sprintf('stty %s', $sttyMode)); } return strlen($ret) > 0 ? $ret : $default; } /** * Asks a confirmation to the user. * * The question will be asked until the user answers by nothing, yes, or no. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param Boolean $default The default answer if the user enters nothing * * @return Boolean true if the user has confirmed, false otherwise */ public function askConfirmation(OutputInterface $output, $question, $default = true) { $answer = 'z'; while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) { $answer = $this->ask($output, $question); } if (false === $default) { return $answer && 'y' == strtolower($answer[0]); } return !$answer || 'y' == strtolower($answer[0]); } /** * Asks a question to the user, the response is hidden * * @param OutputInterface $output An Output instance * @param string|array $question The question * @param Boolean $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not * * @return string The answer * * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden */ public function askHiddenResponse(OutputInterface $output, $question, $fallback = true) { if (defined('PHP_WINDOWS_VERSION_BUILD')) { $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; // handle code running from a phar if ('phar:' === substr(__FILE__, 0, 5)) { $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; copy($exe, $tmpExe); $exe = $tmpExe; } $output->write($question); $value = rtrim(shell_exec($exe)); $output->writeln(''); if (isset($tmpExe)) { unlink($tmpExe); } return $value; } if ($this->hasSttyAvailable()) { $output->write($question); $sttyMode = shell_exec('stty -g'); shell_exec('stty -echo'); $value = fgets($this->inputStream ?: STDIN, 4096); shell_exec(sprintf('stty %s', $sttyMode)); if (false === $value) { throw new \RuntimeException('Aborted'); } $value = trim($value); $output->writeln(''); return $value; } if (false !== $shell = $this->getShell()) { $output->write($question); $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword'; $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); $value = rtrim(shell_exec($command)); $output->writeln(''); return $value; } if ($fallback) { return $this->ask($output, $question); } throw new \RuntimeException('Unable to hide the response'); } /** * Asks for a value and validates the response. * * The validator receives the data to validate. It must return the * validated data when the data is valid and throw an exception * otherwise. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param callable $validator A PHP callback * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param string $default The default answer if none is given by the user * @param array $autocomplete List of values to autocomplete * * @return mixed * * @throws \Exception When any of the validators return an error */ public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null) { $that = $this; $interviewer = function () use ($output, $question, $default, $autocomplete, $that) { return $that->ask($output, $question, $default, $autocomplete); }; return $this->validateAttempts($interviewer, $output, $validator, $attempts); } /** * Asks for a value, hide and validates the response. * * The validator receives the data to validate. It must return the * validated data when the data is valid and throw an exception * otherwise. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param callable $validator A PHP callback * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param Boolean $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not * * @return string The response * * @throws \Exception When any of the validators return an error * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden * */ public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true) { $that = $this; $interviewer = function () use ($output, $question, $fallback, $that) { return $that->askHiddenResponse($output, $question, $fallback); }; return $this->validateAttempts($interviewer, $output, $validator, $attempts); } /** * Sets the input stream to read from when interacting with the user. * * This is mainly useful for testing purpose. * * @param resource $stream The input stream */ public function setInputStream($stream) { $this->inputStream = $stream; } /** * Returns the helper's input stream * * @return string */ public function getInputStream() { return $this->inputStream; } /** * {@inheritDoc} */ public function getName() { return 'dialog'; } /** * Return a valid Unix shell * * @return string|Boolean The valid shell name, false in case no valid shell is found */ private function getShell() { if (null !== self::$shell) { return self::$shell; } self::$shell = false; if (file_exists('/usr/bin/env')) { // handle other OSs with bash/zsh/ksh/csh if available to hide the answer $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) { if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { self::$shell = $sh; break; } } } return self::$shell; } private function hasSttyAvailable() { if (null !== self::$stty) { return self::$stty; } exec('stty 2>&1', $output, $exitcode); return self::$stty = $exitcode === 0; } /** * Validate an attempt * * @param callable $interviewer A callable that will ask for a question and return the result * @param OutputInterface $output An Output instance * @param callable $validator A PHP callback * @param integer $attempts Max number of times to ask before giving up ; false will ask infinitely * * @return string The validated response * * @throws \Exception In case the max number of attempts has been reached and no valid response has been given */ private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts) { $error = null; while (false === $attempts || $attempts--) { if (null !== $error) { $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error')); } try { return call_user_func($validator, $interviewer()); } catch (\Exception $error) { } } throw $error; } } PK]22Console/Helper/TableHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; use InvalidArgumentException; /** * Provides helpers to display table output. * * @author Саша Стаменковић */ class TableHelper extends Helper { const LAYOUT_DEFAULT = 0; const LAYOUT_BORDERLESS = 1; const LAYOUT_COMPACT = 2; /** * Table headers. * * @var array */ private $headers = array(); /** * Table rows. * * @var array */ private $rows = array(); // Rendering options private $paddingChar; private $horizontalBorderChar; private $verticalBorderChar; private $crossingChar; private $cellHeaderFormat; private $cellRowFormat; private $cellRowContentFormat; private $borderFormat; private $padType; /** * Column widths cache. * * @var array */ private $columnWidths = array(); /** * Number of columns cache. * * @var array */ private $numberOfColumns; /** * @var OutputInterface */ private $output; public function __construct() { $this->setLayout(self::LAYOUT_DEFAULT); } /** * Sets table layout type. * * @param int $layout self::LAYOUT_* * * @return TableHelper */ public function setLayout($layout) { switch ($layout) { case self::LAYOUT_BORDERLESS: $this ->setPaddingChar(' ') ->setHorizontalBorderChar('=') ->setVerticalBorderChar(' ') ->setCrossingChar(' ') ->setCellHeaderFormat('%s') ->setCellRowFormat('%s') ->setCellRowContentFormat(' %s ') ->setBorderFormat('%s') ->setPadType(STR_PAD_RIGHT) ; break; case self::LAYOUT_COMPACT: $this ->setPaddingChar(' ') ->setHorizontalBorderChar('') ->setVerticalBorderChar(' ') ->setCrossingChar('') ->setCellHeaderFormat('%s') ->setCellRowFormat('%s') ->setCellRowContentFormat('%s') ->setBorderFormat('%s') ->setPadType(STR_PAD_RIGHT) ; break; case self::LAYOUT_DEFAULT: $this ->setPaddingChar(' ') ->setHorizontalBorderChar('-') ->setVerticalBorderChar('|') ->setCrossingChar('+') ->setCellHeaderFormat('%s') ->setCellRowFormat('%s') ->setCellRowContentFormat(' %s ') ->setBorderFormat('%s') ->setPadType(STR_PAD_RIGHT) ; break; default: throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout)); break; }; return $this; } public function setHeaders(array $headers) { $this->headers = array_values($headers); return $this; } public function setRows(array $rows) { $this->rows = array(); return $this->addRows($rows); } public function addRows(array $rows) { foreach ($rows as $row) { $this->addRow($row); } return $this; } public function addRow(array $row) { $this->rows[] = array_values($row); $keys = array_keys($this->rows); $rowKey = array_pop($keys); foreach ($row as $key => $cellValue) { if (!strstr($cellValue, "\n")) { continue; } $lines = explode("\n", $cellValue); $this->rows[$rowKey][$key] = $lines[0]; unset($lines[0]); foreach ($lines as $lineKey => $line) { $nextRowKey = $rowKey + $lineKey + 1; if (isset($this->rows[$nextRowKey])) { $this->rows[$nextRowKey][$key] = $line; } else { $this->rows[$nextRowKey] = array($key => $line); } } } return $this; } public function setRow($column, array $row) { $this->rows[$column] = $row; return $this; } /** * Sets padding character, used for cell padding. * * @param string $paddingChar * * @return TableHelper */ public function setPaddingChar($paddingChar) { if (!$paddingChar) { throw new \LogicException('The padding char must not be empty'); } $this->paddingChar = $paddingChar; return $this; } /** * Sets horizontal border character. * * @param string $horizontalBorderChar * * @return TableHelper */ public function setHorizontalBorderChar($horizontalBorderChar) { $this->horizontalBorderChar = $horizontalBorderChar; return $this; } /** * Sets vertical border character. * * @param string $verticalBorderChar * * @return TableHelper */ public function setVerticalBorderChar($verticalBorderChar) { $this->verticalBorderChar = $verticalBorderChar; return $this; } /** * Sets crossing character. * * @param string $crossingChar * * @return TableHelper */ public function setCrossingChar($crossingChar) { $this->crossingChar = $crossingChar; return $this; } /** * Sets header cell format. * * @param string $cellHeaderFormat * * @return TableHelper */ public function setCellHeaderFormat($cellHeaderFormat) { $this->cellHeaderFormat = $cellHeaderFormat; return $this; } /** * Sets row cell format. * * @param string $cellRowFormat * * @return TableHelper */ public function setCellRowFormat($cellRowFormat) { $this->cellRowFormat = $cellRowFormat; return $this; } /** * Sets row cell content format. * * @param string $cellRowContentFormat * * @return TableHelper */ public function setCellRowContentFormat($cellRowContentFormat) { $this->cellRowContentFormat = $cellRowContentFormat; return $this; } /** * Sets table border format. * * @param string $borderFormat * * @return TableHelper */ public function setBorderFormat($borderFormat) { $this->borderFormat = $borderFormat; return $this; } /** * Sets cell padding type. * * @param integer $padType STR_PAD_* * * @return TableHelper */ public function setPadType($padType) { $this->padType = $padType; return $this; } /** * Renders table to output. * * Example: * +---------------+-----------------------+------------------+ * | ISBN | Title | Author | * +---------------+-----------------------+------------------+ * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | * +---------------+-----------------------+------------------+ * * @param OutputInterface $output */ public function render(OutputInterface $output) { $this->output = $output; $this->renderRowSeparator(); $this->renderRow($this->headers, $this->cellHeaderFormat); if (!empty($this->headers)) { $this->renderRowSeparator(); } foreach ($this->rows as $row) { $this->renderRow($row, $this->cellRowFormat); } if (!empty($this->rows)) { $this->renderRowSeparator(); } $this->cleanup(); } /** * Renders horizontal header separator. * * Example: +-----+-----------+-------+ */ private function renderRowSeparator() { if (0 === $count = $this->getNumberOfColumns()) { return; } if (!$this->horizontalBorderChar && !$this->crossingChar) { return; } $markup = $this->crossingChar; for ($column = 0; $column < $count; $column++) { $markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column)).$this->crossingChar; } $this->output->writeln(sprintf($this->borderFormat, $markup)); } /** * Renders vertical column separator. */ private function renderColumnSeparator() { $this->output->write(sprintf($this->borderFormat, $this->verticalBorderChar)); } /** * Renders table row. * * Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * * @param array $row * @param string $cellFormat */ private function renderRow(array $row, $cellFormat) { if (empty($row)) { return; } $this->renderColumnSeparator(); for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) { $this->renderCell($row, $column, $cellFormat); $this->renderColumnSeparator(); } $this->output->writeln(''); } /** * Renders table cell with padding. * * @param array $row * @param integer $column * @param string $cellFormat */ private function renderCell(array $row, $column, $cellFormat) { $cell = isset($row[$column]) ? $row[$column] : ''; $width = $this->getColumnWidth($column); // str_pad won't work properly with multi-byte strings, we need to fix the padding if (function_exists('mb_strlen') && false !== $encoding = mb_detect_encoding($cell)) { $width += strlen($cell) - mb_strlen($cell, $encoding); } $width += $this->strlen($cell) - $this->computeLengthWithoutDecoration($cell); $content = sprintf($this->cellRowContentFormat, $cell); $this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->paddingChar, $this->padType))); } /** * Gets number of columns for this table. * * @return int */ private function getNumberOfColumns() { if (null !== $this->numberOfColumns) { return $this->numberOfColumns; } $columns = array(0); $columns[] = count($this->headers); foreach ($this->rows as $row) { $columns[] = count($row); } return $this->numberOfColumns = max($columns); } /** * Gets column width. * * @param integer $column * * @return int */ private function getColumnWidth($column) { if (isset($this->columnWidths[$column])) { return $this->columnWidths[$column]; } $lengths = array(0); $lengths[] = $this->getCellWidth($this->headers, $column); foreach ($this->rows as $row) { $lengths[] = $this->getCellWidth($row, $column); } return $this->columnWidths[$column] = max($lengths) + strlen($this->cellRowContentFormat) - 2; } /** * Gets cell width. * * @param array $row * @param integer $column * * @return int */ private function getCellWidth(array $row, $column) { return isset($row[$column]) ? $this->computeLengthWithoutDecoration($row[$column]) : 0; } /** * Called after rendering to cleanup cache data. */ private function cleanup() { $this->columnWidths = array(); $this->numberOfColumns = null; } private function computeLengthWithoutDecoration($string) { $formatter = $this->output->getFormatter(); $isDecorated = $formatter->isDecorated(); $formatter->setDecorated(false); $string = $formatter->format($string); $formatter->setDecorated($isDecorated); return $this->strlen($string); } /** * {@inheritDoc} */ public function getName() { return 'table'; } } PK]s H#Console/Helper/InputAwareHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputAwareInterface; /** * An implementation of InputAwareInterface for Helpers. * * @author Wouter J */ abstract class InputAwareHelper extends Helper implements InputAwareInterface { protected $input; /** * {@inheritDoc} */ public function setInput(InputInterface $input) { $this->input = $input; } } PK]|po.o.!Console/Helper/ProgressHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; /** * The Progress class provides helpers to display progress output. * * @author Chris Jones * @author Fabien Potencier */ class ProgressHelper extends Helper { const FORMAT_QUIET = ' %percent%%'; const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%'; const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%'; const FORMAT_QUIET_NOMAX = ' %current%'; const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]'; const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%'; // options private $barWidth = 28; private $barChar = '='; private $emptyBarChar = '-'; private $progressChar = '>'; private $format = null; private $redrawFreq = 1; private $lastMessagesLength; private $barCharOriginal; /** * @var OutputInterface */ private $output; /** * Current step * * @var integer */ private $current; /** * Maximum number of steps * * @var integer */ private $max; /** * Start time of the progress bar * * @var integer */ private $startTime; /** * List of formatting variables * * @var array */ private $defaultFormatVars = array( 'current', 'max', 'bar', 'percent', 'elapsed', ); /** * Available formatting variables * * @var array */ private $formatVars; /** * Stored format part widths (used for padding) * * @var array */ private $widths = array( 'current' => 4, 'max' => 4, 'percent' => 3, 'elapsed' => 6, ); /** * Various time formats * * @var array */ private $timeFormats = array( array(0, '???'), array(2, '1 sec'), array(59, 'secs', 1), array(60, '1 min'), array(3600, 'mins', 60), array(5400, '1 hr'), array(86400, 'hrs', 3600), array(129600, '1 day'), array(604800, 'days', 86400), ); /** * Sets the progress bar width. * * @param int $size The progress bar size */ public function setBarWidth($size) { $this->barWidth = (int) $size; } /** * Sets the bar character. * * @param string $char A character */ public function setBarCharacter($char) { $this->barChar = $char; } /** * Sets the empty bar character. * * @param string $char A character */ public function setEmptyBarCharacter($char) { $this->emptyBarChar = $char; } /** * Sets the progress bar character. * * @param string $char A character */ public function setProgressCharacter($char) { $this->progressChar = $char; } /** * Sets the progress bar format. * * @param string $format The format */ public function setFormat($format) { $this->format = $format; } /** * Sets the redraw frequency. * * @param int $freq The frequency in steps */ public function setRedrawFrequency($freq) { $this->redrawFreq = (int) $freq; } /** * Starts the progress output. * * @param OutputInterface $output An Output instance * @param integer|null $max Maximum steps */ public function start(OutputInterface $output, $max = null) { $this->startTime = time(); $this->current = 0; $this->max = (int) $max; $this->output = $output; $this->lastMessagesLength = 0; $this->barCharOriginal = ''; if (null === $this->format) { switch ($output->getVerbosity()) { case OutputInterface::VERBOSITY_QUIET: $this->format = self::FORMAT_QUIET_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_QUIET; } break; case OutputInterface::VERBOSITY_VERBOSE: case OutputInterface::VERBOSITY_VERY_VERBOSE: case OutputInterface::VERBOSITY_DEBUG: $this->format = self::FORMAT_VERBOSE_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_VERBOSE; } break; default: $this->format = self::FORMAT_NORMAL_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_NORMAL; } break; } } $this->initialize(); } /** * Advances the progress output X steps. * * @param integer $step Number of steps to advance * @param Boolean $redraw Whether to redraw or not * * @throws \LogicException */ public function advance($step = 1, $redraw = false) { $this->setCurrent($this->current + $step, $redraw); } /** * Sets the current progress. * * @param integer $current The current progress * @param Boolean $redraw Whether to redraw or not * * @throws \LogicException */ public function setCurrent($current, $redraw = false) { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling setCurrent().'); } $current = (int) $current; if ($current < $this->current) { throw new \LogicException('You can\'t regress the progress bar'); } if (0 === $this->current) { $redraw = true; } $prevPeriod = intval($this->current / $this->redrawFreq); $this->current = $current; $currPeriod = intval($this->current / $this->redrawFreq); if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) { $this->display(); } } /** * Outputs the current progress string. * * @param Boolean $finish Forces the end result * * @throws \LogicException */ public function display($finish = false) { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling display().'); } $message = $this->format; foreach ($this->generate($finish) as $name => $value) { $message = str_replace("%{$name}%", $value, $message); } $this->overwrite($this->output, $message); } /** * Removes the progress bar from the current line. * * This is useful if you wish to write some output * while a progress bar is running. * Call display() to show the progress bar again. */ public function clear() { $this->overwrite($this->output, ''); } /** * Finishes the progress output. */ public function finish() { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling finish().'); } if (null !== $this->startTime) { if (!$this->max) { $this->barChar = $this->barCharOriginal; $this->display(true); } $this->startTime = null; $this->output->writeln(''); $this->output = null; } } /** * Initializes the progress helper. */ private function initialize() { $this->formatVars = array(); foreach ($this->defaultFormatVars as $var) { if (false !== strpos($this->format, "%{$var}%")) { $this->formatVars[$var] = true; } } if ($this->max > 0) { $this->widths['max'] = $this->strlen($this->max); $this->widths['current'] = $this->widths['max']; } else { $this->barCharOriginal = $this->barChar; $this->barChar = $this->emptyBarChar; } } /** * Generates the array map of format variables to values. * * @param Boolean $finish Forces the end result * * @return array Array of format vars and values */ private function generate($finish = false) { $vars = array(); $percent = 0; if ($this->max > 0) { $percent = (float) $this->current / $this->max; } if (isset($this->formatVars['bar'])) { $completeBars = 0; if ($this->max > 0) { $completeBars = floor($percent * $this->barWidth); } else { if (!$finish) { $completeBars = floor($this->current % $this->barWidth); } else { $completeBars = $this->barWidth; } } $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar); $bar = str_repeat($this->barChar, $completeBars); if ($completeBars < $this->barWidth) { $bar .= $this->progressChar; $bar .= str_repeat($this->emptyBarChar, $emptyBars); } $vars['bar'] = $bar; } if (isset($this->formatVars['elapsed'])) { $elapsed = time() - $this->startTime; $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT); } if (isset($this->formatVars['current'])) { $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT); } if (isset($this->formatVars['max'])) { $vars['max'] = $this->max; } if (isset($this->formatVars['percent'])) { $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT); } return $vars; } /** * Converts seconds into human-readable format. * * @param integer $secs Number of seconds * * @return string Time in readable format */ private function humaneTime($secs) { $text = ''; foreach ($this->timeFormats as $format) { if ($secs < $format[0]) { if (count($format) == 2) { $text = $format[1]; break; } else { $text = ceil($secs / $format[2]).' '.$format[1]; break; } } } return $text; } /** * Overwrites a previous message to the output. * * @param OutputInterface $output An Output instance * @param string $message The message */ private function overwrite(OutputInterface $output, $message) { $length = $this->strlen($message); // append whitespace to match the last line's length if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) { $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); } // carriage return $output->write("\x0D"); $output->write($message); $this->lastMessagesLength = $this->strlen($message); } /** * {@inheritDoc} */ public function getName() { return 'progress'; } } PK]z"Console/Helper/HelperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * HelperInterface is the interface all helpers must implement. * * @author Fabien Potencier * * @api */ interface HelperInterface { /** * Sets the helper set associated with this helper. * * @param HelperSet $helperSet A HelperSet instance * * @api */ public function setHelperSet(HelperSet $helperSet = null); /** * Gets the helper set associated with this helper. * * @return HelperSet A HelperSet instance * * @api */ public function getHelperSet(); /** * Returns the canonical name of this helper. * * @return string The canonical name * * @api */ public function getName(); } PK]onj&&*Console/Formatter/OutputFormatterStyle.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter style class for defining styles. * * @author Konstantin Kudryashov * * @api */ class OutputFormatterStyle implements OutputFormatterStyleInterface { private static $availableForegroundColors = array( 'black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37 ); private static $availableBackgroundColors = array( 'black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47 ); private static $availableOptions = array( 'bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8 ); private $foreground; private $background; private $options = array(); /** * Initializes output formatter style. * * @param string|null $foreground The style foreground color name * @param string|null $background The style background color name * @param array $options The style options * * @api */ public function __construct($foreground = null, $background = null, array $options = array()) { if (null !== $foreground) { $this->setForeground($foreground); } if (null !== $background) { $this->setBackground($background); } if (count($options)) { $this->setOptions($options); } } /** * Sets style foreground color. * * @param string|null $color The color name * * @throws \InvalidArgumentException When the color name isn't defined * * @api */ public function setForeground($color = null) { if (null === $color) { $this->foreground = null; return; } if (!isset(static::$availableForegroundColors[$color])) { throw new \InvalidArgumentException(sprintf( 'Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors)) )); } $this->foreground = static::$availableForegroundColors[$color]; } /** * Sets style background color. * * @param string|null $color The color name * * @throws \InvalidArgumentException When the color name isn't defined * * @api */ public function setBackground($color = null) { if (null === $color) { $this->background = null; return; } if (!isset(static::$availableBackgroundColors[$color])) { throw new \InvalidArgumentException(sprintf( 'Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors)) )); } $this->background = static::$availableBackgroundColors[$color]; } /** * Sets some specific style option. * * @param string $option The option name * * @throws \InvalidArgumentException When the option name isn't defined * * @api */ public function setOption($option) { if (!isset(static::$availableOptions[$option])) { throw new \InvalidArgumentException(sprintf( 'Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)) )); } if (false === array_search(static::$availableOptions[$option], $this->options)) { $this->options[] = static::$availableOptions[$option]; } } /** * Unsets some specific style option. * * @param string $option The option name * * @throws \InvalidArgumentException When the option name isn't defined * */ public function unsetOption($option) { if (!isset(static::$availableOptions[$option])) { throw new \InvalidArgumentException(sprintf( 'Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)) )); } $pos = array_search(static::$availableOptions[$option], $this->options); if (false !== $pos) { unset($this->options[$pos]); } } /** * Sets multiple style options at once. * * @param array $options */ public function setOptions(array $options) { $this->options = array(); foreach ($options as $option) { $this->setOption($option); } } /** * Applies the style to a given text. * * @param string $text The text to style * * @return string */ public function apply($text) { $codes = array(); if (null !== $this->foreground) { $codes[] = $this->foreground; } if (null !== $this->background) { $codes[] = $this->background; } if (count($this->options)) { $codes = array_merge($codes, $this->options); } if (0 === count($codes)) { return $text; } return sprintf("\033[%sm%s\033[0m", implode(';', $codes), $text); } } PK]v /Console/Formatter/OutputFormatterStyleStack.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * @author Jean-François Simon */ class OutputFormatterStyleStack { /** * @var OutputFormatterStyleInterface[] */ private $styles; /** * @var OutputFormatterStyleInterface */ private $emptyStyle; /** * Constructor. * * @param OutputFormatterStyleInterface|null $emptyStyle */ public function __construct(OutputFormatterStyleInterface $emptyStyle = null) { $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle(); $this->reset(); } /** * Resets stack (ie. empty internal arrays). */ public function reset() { $this->styles = array(); } /** * Pushes a style in the stack. * * @param OutputFormatterStyleInterface $style */ public function push(OutputFormatterStyleInterface $style) { $this->styles[] = $style; } /** * Pops a style from the stack. * * @param OutputFormatterStyleInterface|null $style * * @return OutputFormatterStyleInterface * * @throws \InvalidArgumentException When style tags incorrectly nested */ public function pop(OutputFormatterStyleInterface $style = null) { if (empty($this->styles)) { return $this->emptyStyle; } if (null === $style) { return array_pop($this->styles); } foreach (array_reverse($this->styles, true) as $index => $stackedStyle) { if ($style->apply('') === $stackedStyle->apply('')) { $this->styles = array_slice($this->styles, 0, $index); return $stackedStyle; } } throw new \InvalidArgumentException('Incorrectly nested style tag found.'); } /** * Computes current style with stacks top codes. * * @return OutputFormatterStyle */ public function getCurrent() { if (empty($this->styles)) { return $this->emptyStyle; } return $this->styles[count($this->styles)-1]; } /** * @param OutputFormatterStyleInterface $emptyStyle * * @return OutputFormatterStyleStack */ public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle) { $this->emptyStyle = $emptyStyle; return $this; } /** * @return OutputFormatterStyleInterface */ public function getEmptyStyle() { return $this->emptyStyle; } } PK]53Console/Formatter/OutputFormatterStyleInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter style interface for defining styles. * * @author Konstantin Kudryashov * * @api */ interface OutputFormatterStyleInterface { /** * Sets style foreground color. * * @param string $color The color name * * @api */ public function setForeground($color = null); /** * Sets style background color. * * @param string $color The color name * * @api */ public function setBackground($color = null); /** * Sets some specific style option. * * @param string $option The option name * * @api */ public function setOption($option); /** * Unsets some specific style option. * * @param string $option The option name */ public function unsetOption($option); /** * Sets multiple style options at once. * * @param array $options */ public function setOptions(array $options); /** * Applies the style to a given text. * * @param string $text The text to style * * @return string */ public function apply($text); } PK]Jp.Console/Formatter/OutputFormatterInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter interface for console output. * * @author Konstantin Kudryashov * * @api */ interface OutputFormatterInterface { /** * Sets the decorated flag. * * @param Boolean $decorated Whether to decorate the messages or not * * @api */ public function setDecorated($decorated); /** * Gets the decorated flag. * * @return Boolean true if the output will decorate messages, false otherwise * * @api */ public function isDecorated(); /** * Sets a new style. * * @param string $name The style name * @param OutputFormatterStyleInterface $style The style instance * * @api */ public function setStyle($name, OutputFormatterStyleInterface $style); /** * Checks if output formatter has style with specified name. * * @param string $name * * @return Boolean * * @api */ public function hasStyle($name); /** * Gets style options from style with specified name. * * @param string $name * * @return OutputFormatterStyleInterface * * @api */ public function getStyle($name); /** * Formats a message according to the given styles. * * @param string $message The message to style * * @return string The styled message * * @api */ public function format($message); } PK]l%Console/Formatter/OutputFormatter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter class for console output. * * @author Konstantin Kudryashov * * @api */ class OutputFormatter implements OutputFormatterInterface { private $decorated; private $styles = array(); private $styleStack; /** * Escapes "<" special char in given text. * * @param string $text Text to escape * * @return string Escaped text */ public static function escape($text) { return preg_replace('/([^\\\\]?) FormatterStyle" instances * * @api */ public function __construct($decorated = false, array $styles = array()) { $this->decorated = (Boolean) $decorated; $this->setStyle('error', new OutputFormatterStyle('white', 'red')); $this->setStyle('info', new OutputFormatterStyle('green')); $this->setStyle('comment', new OutputFormatterStyle('yellow')); $this->setStyle('question', new OutputFormatterStyle('black', 'cyan')); foreach ($styles as $name => $style) { $this->setStyle($name, $style); } $this->styleStack = new OutputFormatterStyleStack(); } /** * Sets the decorated flag. * * @param Boolean $decorated Whether to decorate the messages or not * * @api */ public function setDecorated($decorated) { $this->decorated = (Boolean) $decorated; } /** * Gets the decorated flag. * * @return Boolean true if the output will decorate messages, false otherwise * * @api */ public function isDecorated() { return $this->decorated; } /** * Sets a new style. * * @param string $name The style name * @param OutputFormatterStyleInterface $style The style instance * * @api */ public function setStyle($name, OutputFormatterStyleInterface $style) { $this->styles[strtolower($name)] = $style; } /** * Checks if output formatter has style with specified name. * * @param string $name * * @return Boolean * * @api */ public function hasStyle($name) { return isset($this->styles[strtolower($name)]); } /** * Gets style options from style with specified name. * * @param string $name * * @return OutputFormatterStyleInterface * * @throws \InvalidArgumentException When style isn't defined * * @api */ public function getStyle($name) { if (!$this->hasStyle($name)) { throw new \InvalidArgumentException(sprintf('Undefined style: %s', $name)); } return $this->styles[strtolower($name)]; } /** * Formats a message according to the given styles. * * @param string $message The message to style * * @return string The styled message * * @api */ public function format($message) { $offset = 0; $output = ''; $tagRegex = '[a-z][a-z0-9_=;-]*'; preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#isx", $message, $matches, PREG_OFFSET_CAPTURE); foreach ($matches[0] as $i => $match) { $pos = $match[1]; $text = $match[0]; // add the text up to the next tag $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset)); $offset = $pos + strlen($text); // opening tag? if ($open = '/' != $text[1]) { $tag = $matches[1][$i][0]; } else { $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : ''; } if (!$open && !$tag) { // $this->styleStack->pop(); } elseif ($pos && '\\' == $message[$pos - 1]) { // escaped tag $output .= $this->applyCurrentStyle($text); } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) { $output .= $this->applyCurrentStyle($text); } elseif ($open) { $this->styleStack->push($style); } else { $this->styleStack->pop($style); } } $output .= $this->applyCurrentStyle(substr($message, $offset)); return str_replace('\\<', '<', $output); } /** * @return OutputFormatterStyleStack */ public function getStyleStack() { return $this->styleStack; } /** * Tries to create new style instance from string. * * @param string $string * * @return OutputFormatterStyle|Boolean false if string is not format string */ private function createStyleFromString($string) { if (isset($this->styles[$string])) { return $this->styles[$string]; } if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) { return false; } $style = new OutputFormatterStyle(); foreach ($matches as $match) { array_shift($match); if ('fg' == $match[0]) { $style->setForeground($match[1]); } elseif ('bg' == $match[0]) { $style->setBackground($match[1]); } else { $style->setOption($match[1]); } } return $style; } /** * Applies current style from stack to text, if must be applied. * * @param string $text Input text * * @return string Styled text */ private function applyCurrentStyle($text) { return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text; } } PK]zM M "Console/Output/OutputInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * OutputInterface is the interface implemented by all Output classes. * * @author Fabien Potencier * * @api */ interface OutputInterface { const VERBOSITY_QUIET = 0; const VERBOSITY_NORMAL = 1; const VERBOSITY_VERBOSE = 2; const VERBOSITY_VERY_VERBOSE = 3; const VERBOSITY_DEBUG = 4; const OUTPUT_NORMAL = 0; const OUTPUT_RAW = 1; const OUTPUT_PLAIN = 2; /** * Writes a message to the output. * * @param string|array $messages The message as an array of lines or a single string * @param Boolean $newline Whether to add a newline * @param integer $type The type of output (one of the OUTPUT constants) * * @throws \InvalidArgumentException When unknown output type is given * * @api */ public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL); /** * Writes a message to the output and adds a newline at the end. * * @param string|array $messages The message as an array of lines of a single string * @param integer $type The type of output (one of the OUTPUT constants) * * @throws \InvalidArgumentException When unknown output type is given * * @api */ public function writeln($messages, $type = self::OUTPUT_NORMAL); /** * Sets the verbosity of the output. * * @param integer $level The level of verbosity (one of the VERBOSITY constants) * * @api */ public function setVerbosity($level); /** * Gets the current verbosity of the output. * * @return integer The current level of verbosity (one of the VERBOSITY constants) * * @api */ public function getVerbosity(); /** * Sets the decorated flag. * * @param Boolean $decorated Whether to decorate the messages * * @api */ public function setDecorated($decorated); /** * Gets the decorated flag. * * @return Boolean true if the output will decorate messages, false otherwise * * @api */ public function isDecorated(); /** * Sets output formatter. * * @param OutputFormatterInterface $formatter * * @api */ public function setFormatter(OutputFormatterInterface $formatter); /** * Returns current output formatter instance. * * @return OutputFormatterInterface * * @api */ public function getFormatter(); } PK]F$_Console/Output/NullOutput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * NullOutput suppresses all output. * * $output = new NullOutput(); * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class NullOutput implements OutputInterface { /** * {@inheritdoc} */ public function setFormatter(OutputFormatterInterface $formatter) { // do nothing } /** * {@inheritdoc} */ public function getFormatter() { // to comply with the interface we must return a OutputFormatterInterface return new OutputFormatter(); } /** * {@inheritdoc} */ public function setDecorated($decorated) { // do nothing } /** * {@inheritdoc} */ public function isDecorated() { return false; } /** * {@inheritdoc} */ public function setVerbosity($level) { // do nothing } /** * {@inheritdoc} */ public function getVerbosity() { return self::VERBOSITY_QUIET; } /** * {@inheritdoc} */ public function writeln($messages, $type = self::OUTPUT_NORMAL) { // do nothing } /** * {@inheritdoc} */ public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) { // do nothing } } PK],QM M Console/Output/StreamOutput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * StreamOutput writes the output to a given stream. * * Usage: * * $output = new StreamOutput(fopen('php://stdout', 'w')); * * As `StreamOutput` can use any stream, you can also use a file: * * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); * * @author Fabien Potencier * * @api */ class StreamOutput extends Output { private $stream; /** * Constructor. * * @param mixed $stream A stream resource * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param Boolean|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) * * @throws \InvalidArgumentException When first argument is not a real stream * * @api */ public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) { if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) { throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); } $this->stream = $stream; if (null === $decorated) { $decorated = $this->hasColorSupport(); } parent::__construct($verbosity, $decorated, $formatter); } /** * Gets the stream attached to this StreamOutput instance. * * @return resource A stream resource */ public function getStream() { return $this->stream; } /** * {@inheritdoc} */ protected function doWrite($message, $newline) { if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) { // @codeCoverageIgnoreStart // should never happen throw new \RuntimeException('Unable to write output.'); // @codeCoverageIgnoreEnd } fflush($this->stream); } /** * Returns true if the stream supports colorization. * * Colorization is disabled if not supported by the stream: * * - Windows without Ansicon and ConEmu * - non tty consoles * * @return Boolean true if the stream supports colorization, false otherwise */ protected function hasColorSupport() { // @codeCoverageIgnoreStart if (DIRECTORY_SEPARATOR == '\\') { return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI'); } return function_exists('posix_isatty') && @posix_isatty($this->stream); // @codeCoverageIgnoreEnd } } PK]t|X4hh!Console/Output/BufferedOutput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; /** * @author Jean-François Simon */ class BufferedOutput extends Output { /** * @var string */ private $buffer = ''; /** * Empties buffer and returns its content. * * @return string */ public function fetch() { $content = $this->buffer; $this->buffer = ''; return $content; } /** * {@inheritdoc} */ protected function doWrite($message, $newline) { $this->buffer .= $message; if ($newline) { $this->buffer .= "\n"; } } } PK]0KK)Console/Output/ConsoleOutputInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; /** * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. * This adds information about stderr output stream. * * @author Dariusz Górecki */ interface ConsoleOutputInterface extends OutputInterface { /** * Gets the OutputInterface for errors. * * @return OutputInterface */ public function getErrorOutput(); /** * Sets the OutputInterface used for errors. * * @param OutputInterface $error */ public function setErrorOutput(OutputInterface $error); } PK]sQ;;Console/Output/Output.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Formatter\OutputFormatter; /** * Base class for output classes. * * There are five levels of verbosity: * * * normal: no option passed (normal output) * * verbose: -v (more output) * * very verbose: -vv (highly extended output) * * debug: -vvv (all debug output) * * quiet: -q (no output) * * @author Fabien Potencier * * @api */ abstract class Output implements OutputInterface { private $verbosity; private $formatter; /** * Constructor. * * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param Boolean $decorated Whether to decorate messages * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) * * @api */ public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null) { $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; $this->formatter = $formatter ?: new OutputFormatter(); $this->formatter->setDecorated($decorated); } /** * {@inheritdoc} */ public function setFormatter(OutputFormatterInterface $formatter) { $this->formatter = $formatter; } /** * {@inheritdoc} */ public function getFormatter() { return $this->formatter; } /** * {@inheritdoc} */ public function setDecorated($decorated) { $this->formatter->setDecorated($decorated); } /** * {@inheritdoc} */ public function isDecorated() { return $this->formatter->isDecorated(); } /** * {@inheritdoc} */ public function setVerbosity($level) { $this->verbosity = (int) $level; } /** * {@inheritdoc} */ public function getVerbosity() { return $this->verbosity; } public function isQuiet() { return self::VERBOSITY_QUIET === $this->verbosity; } public function isVerbose() { return self::VERBOSITY_VERBOSE <= $this->verbosity; } public function isVeryVerbose() { return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity; } public function isDebug() { return self::VERBOSITY_DEBUG <= $this->verbosity; } /** * {@inheritdoc} */ public function writeln($messages, $type = self::OUTPUT_NORMAL) { $this->write($messages, true, $type); } /** * {@inheritdoc} */ public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) { if (self::VERBOSITY_QUIET === $this->verbosity) { return; } $messages = (array) $messages; foreach ($messages as $message) { switch ($type) { case OutputInterface::OUTPUT_NORMAL: $message = $this->formatter->format($message); break; case OutputInterface::OUTPUT_RAW: break; case OutputInterface::OUTPUT_PLAIN: $message = strip_tags($this->formatter->format($message)); break; default: throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type)); } $this->doWrite($message, $newline); } } /** * Writes a message to the output. * * @param string $message A message to write to the output * @param Boolean $newline Whether to add a newline or not */ abstract protected function doWrite($message, $newline); } PK]ϱ} } Console/Output/ConsoleOutput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * ConsoleOutput is the default class for all CLI output. It uses STDOUT. * * This class is a convenient wrapper around `StreamOutput`. * * $output = new ConsoleOutput(); * * This is equivalent to: * * $output = new StreamOutput(fopen('php://stdout', 'w')); * * @author Fabien Potencier * * @api */ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface { private $stderr; /** * Constructor. * * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param Boolean|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) * * @api */ public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) { $outputStream = 'php://stdout'; if (!$this->hasStdoutSupport()) { $outputStream = 'php://output'; } parent::__construct(fopen($outputStream, 'w'), $verbosity, $decorated, $formatter); $this->stderr = new StreamOutput(fopen('php://stderr', 'w'), $verbosity, $decorated, $formatter); } /** * {@inheritdoc} */ public function setDecorated($decorated) { parent::setDecorated($decorated); $this->stderr->setDecorated($decorated); } /** * {@inheritdoc} */ public function setFormatter(OutputFormatterInterface $formatter) { parent::setFormatter($formatter); $this->stderr->setFormatter($formatter); } /** * {@inheritdoc} */ public function setVerbosity($level) { parent::setVerbosity($level); $this->stderr->setVerbosity($level); } /** * {@inheritdoc} */ public function getErrorOutput() { return $this->stderr; } /** * {@inheritdoc} */ public function setErrorOutput(OutputInterface $error) { $this->stderr = $error; } /** * Returns true if current environment supports writing console output to * STDOUT. * * IBM iSeries (OS400) exhibits character-encoding issues when writing to * STDOUT and doesn't properly convert ASCII to EBCDIC, resulting in garbage * output. * * @return boolean */ protected function hasStdoutSupport() { return ('OS400' != php_uname('s')); } } PK]||-&%Console/Event/ConsoleCommandEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; /** * Allows to do things before the command is executed. * * @author Fabien Potencier */ class ConsoleCommandEvent extends ConsoleEvent { } PK] Console/Event/ConsoleEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\EventDispatcher\Event; /** * Allows to inspect input and output of a command. * * @author Francesco Levorato */ class ConsoleEvent extends Event { protected $command; private $input; private $output; public function __construct(Command $command, InputInterface $input, OutputInterface $output) { $this->command = $command; $this->input = $input; $this->output = $output; } /** * Gets the command that is executed. * * @return Command A Command instance */ public function getCommand() { return $this->command; } /** * Gets the input instance. * * @return InputInterface An InputInterface instance */ public function getInput() { return $this->input; } /** * Gets the output instance. * * @return OutputInterface An OutputInterface instance */ public function getOutput() { return $this->output; } } PK]sKAA'Console/Event/ConsoleExceptionEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Allows to handle exception thrown in a command. * * @author Fabien Potencier */ class ConsoleExceptionEvent extends ConsoleEvent { private $exception; private $exitCode; public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode) { parent::__construct($command, $input, $output); $this->setException($exception); $this->exitCode = (int) $exitCode; } /** * Returns the thrown exception. * * @return \Exception The thrown exception */ public function getException() { return $this->exception; } /** * Replaces the thrown exception. * * This exception will be thrown if no response is set in the event. * * @param \Exception $exception The thrown exception */ public function setException(\Exception $exception) { $this->exception = $exception; } /** * Gets the exit code. * * @return integer The command exit code */ public function getExitCode() { return $this->exitCode; } } PK]Z&&'Console/Event/ConsoleTerminateEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Allows to manipulate the exit code of a command after its execution. * * @author Francesco Levorato */ class ConsoleTerminateEvent extends ConsoleEvent { /** * The exit code of the command. * * @var integer */ private $exitCode; public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode) { parent::__construct($command, $input, $output); $this->setExitCode($exitCode); } /** * Sets the exit code. * * @param integer $exitCode The command exit code */ public function setExitCode($exitCode) { $this->exitCode = (int) $exitCode; } /** * Gets the exit code. * * @return integer The command exit code */ public function getExitCode() { return $this->exitCode; } } PK]\0EConsole/ConsoleEvents.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console; /** * Contains all events dispatched by an Application. * * @author Francesco Levorato */ final class ConsoleEvents { /** * The COMMAND event allows you to attach listeners before any command is * executed by the console. It also allows you to modify the command, input and output * before they are handled to the command. * * The event listener method receives a Symfony\Component\Console\Event\ConsoleCommandEvent * instance. * * @var string */ const COMMAND = 'console.command'; /** * The TERMINATE event allows you to attach listeners after a command is * executed by the console. * * The event listener method receives a Symfony\Component\Console\Event\ConsoleTerminateEvent * instance. * * @var string */ const TERMINATE = 'console.terminate'; /** * The EXCEPTION event occurs when an uncaught exception appears. * * This event allows you to deal with the exception or * to modify the thrown exception. The event listener method receives * a Symfony\Component\Console\Event\ConsoleExceptionEvent * instance. * * @var string */ const EXCEPTION = 'console.exception'; } PK]m_ _ Console/Command/HelpCommand.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Helper\DescriptorHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * HelpCommand displays the help for a given command. * * @author Fabien Potencier */ class HelpCommand extends Command { private $command; /** * {@inheritdoc} */ protected function configure() { $this->ignoreValidationErrors(); $this ->setName('help') ->setDefinition(array( new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats', 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), )) ->setDescription('Displays help for a command') ->setHelp(<<%command.name% command displays help for a given command: php %command.full_name% list You can also output the help in other formats by using the --format option: php %command.full_name% --format=xml list To display the list of available commands, please use the list command. EOF ) ; } /** * Sets the command * * @param Command $command The command to set */ public function setCommand(Command $command) { $this->command = $command; } /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { if (null === $this->command) { $this->command = $this->getApplication()->find($input->getArgument('command_name')); } if ($input->getOption('xml')) { $input->setOption('format', 'xml'); } $helper = new DescriptorHelper(); $helper->describe($output, $this->command, array( 'format' => $input->getOption('format'), 'raw' => $input->getOption('raw'), )); $this->command = null; } } PK]Ƙ7@7@Console/Command/Command.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Application; use Symfony\Component\Console\Helper\HelperSet; /** * Base class for all commands. * * @author Fabien Potencier * * @api */ class Command { private $application; private $name; private $aliases = array(); private $definition; private $help; private $description; private $ignoreValidationErrors = false; private $applicationDefinitionMerged = false; private $applicationDefinitionMergedWithArgs = false; private $code; private $synopsis; private $helperSet; /** * Constructor. * * @param string|null $name The name of the command; passing null means it must be set in configure() * * @throws \LogicException When the command name is empty * * @api */ public function __construct($name = null) { $this->definition = new InputDefinition(); if (null !== $name) { $this->setName($name); } $this->configure(); if (!$this->name) { throw new \LogicException('The command name cannot be empty.'); } } /** * Ignores validation errors. * * This is mainly useful for the help command. */ public function ignoreValidationErrors() { $this->ignoreValidationErrors = true; } /** * Sets the application instance for this command. * * @param Application $application An Application instance * * @api */ public function setApplication(Application $application = null) { $this->application = $application; if ($application) { $this->setHelperSet($application->getHelperSet()); } else { $this->helperSet = null; } } /** * Sets the helper set. * * @param HelperSet $helperSet A HelperSet instance */ public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; } /** * Gets the helper set. * * @return HelperSet A HelperSet instance */ public function getHelperSet() { return $this->helperSet; } /** * Gets the application instance for this command. * * @return Application An Application instance * * @api */ public function getApplication() { return $this->application; } /** * Checks whether the command is enabled or not in the current environment * * Override this to check for x or y and return false if the command can not * run properly under the current conditions. * * @return Boolean */ public function isEnabled() { return true; } /** * Configures the current command. */ protected function configure() { } /** * Executes the current command. * * This method is not abstract because you can use this class * as a concrete class. In this case, instead of defining the * execute() method, you set the code to execute by passing * a Closure to the setCode() method. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * * @return null|integer null or 0 if everything went fine, or an error code * * @throws \LogicException When this abstract method is not implemented * @see setCode() */ protected function execute(InputInterface $input, OutputInterface $output) { throw new \LogicException('You must override the execute() method in the concrete command class.'); } /** * Interacts with the user. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance */ protected function interact(InputInterface $input, OutputInterface $output) { } /** * Initializes the command just after the input has been validated. * * This is mainly useful when a lot of commands extends one main command * where some things need to be initialized based on the input arguments and options. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance */ protected function initialize(InputInterface $input, OutputInterface $output) { } /** * Runs the command. * * The code to execute is either defined directly with the * setCode() method or by overriding the execute() method * in a sub-class. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * * @return integer The command exit code * * @throws \Exception * * @see setCode() * @see execute() * * @api */ public function run(InputInterface $input, OutputInterface $output) { // force the creation of the synopsis before the merge with the app definition $this->getSynopsis(); // add the application arguments and options $this->mergeApplicationDefinition(); // bind the input against the command specific arguments/options try { $input->bind($this->definition); } catch (\Exception $e) { if (!$this->ignoreValidationErrors) { throw $e; } } $this->initialize($input, $output); if ($input->isInteractive()) { $this->interact($input, $output); } $input->validate(); if ($this->code) { $statusCode = call_user_func($this->code, $input, $output); } else { $statusCode = $this->execute($input, $output); } return is_numeric($statusCode) ? (int) $statusCode : 0; } /** * Sets the code to execute when running this command. * * If this method is used, it overrides the code defined * in the execute() method. * * @param callable $code A callable(InputInterface $input, OutputInterface $output) * * @return Command The current instance * * @throws \InvalidArgumentException * * @see execute() * * @api */ public function setCode($code) { if (!is_callable($code)) { throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.'); } $this->code = $code; return $this; } /** * Merges the application definition with the command definition. * * This method is not part of public API and should not be used directly. * * @param Boolean $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments */ public function mergeApplicationDefinition($mergeArgs = true) { if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) { return; } if ($mergeArgs) { $currentArguments = $this->definition->getArguments(); $this->definition->setArguments($this->application->getDefinition()->getArguments()); $this->definition->addArguments($currentArguments); } $this->definition->addOptions($this->application->getDefinition()->getOptions()); $this->applicationDefinitionMerged = true; if ($mergeArgs) { $this->applicationDefinitionMergedWithArgs = true; } } /** * Sets an array of argument and option instances. * * @param array|InputDefinition $definition An array of argument and option instances or a definition instance * * @return Command The current instance * * @api */ public function setDefinition($definition) { if ($definition instanceof InputDefinition) { $this->definition = $definition; } else { $this->definition->setDefinition($definition); } $this->applicationDefinitionMerged = false; return $this; } /** * Gets the InputDefinition attached to this Command. * * @return InputDefinition An InputDefinition instance * * @api */ public function getDefinition() { return $this->definition; } /** * Gets the InputDefinition to be used to create XML and Text representations of this Command. * * Can be overridden to provide the original command representation when it would otherwise * be changed by merging with the application InputDefinition. * * This method is not part of public API and should not be used directly. * * @return InputDefinition An InputDefinition instance */ public function getNativeDefinition() { return $this->getDefinition(); } /** * Adds an argument. * * @param string $name The argument name * @param integer $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL * @param string $description A description text * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) * * @return Command The current instance * * @api */ public function addArgument($name, $mode = null, $description = '', $default = null) { $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); return $this; } /** * Adds an option. * * @param string $name The option name * @param string $shortcut The shortcut (can be null) * @param integer $mode The option mode: One of the InputOption::VALUE_* constants * @param string $description A description text * @param mixed $default The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE) * * @return Command The current instance * * @api */ public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null) { $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); return $this; } /** * Sets the name of the command. * * This method can set both the namespace and the name if * you separate them by a colon (:) * * $command->setName('foo:bar'); * * @param string $name The command name * * @return Command The current instance * * @throws \InvalidArgumentException When the name is invalid * * @api */ public function setName($name) { $this->validateName($name); $this->name = $name; return $this; } /** * Returns the command name. * * @return string The command name * * @api */ public function getName() { return $this->name; } /** * Sets the description for the command. * * @param string $description The description for the command * * @return Command The current instance * * @api */ public function setDescription($description) { $this->description = $description; return $this; } /** * Returns the description for the command. * * @return string The description for the command * * @api */ public function getDescription() { return $this->description; } /** * Sets the help for the command. * * @param string $help The help for the command * * @return Command The current instance * * @api */ public function setHelp($help) { $this->help = $help; return $this; } /** * Returns the help for the command. * * @return string The help for the command * * @api */ public function getHelp() { return $this->help; } /** * Returns the processed help for the command replacing the %command.name% and * %command.full_name% patterns with the real values dynamically. * * @return string The processed help for the command */ public function getProcessedHelp() { $name = $this->name; $placeholders = array( '%command.name%', '%command.full_name%' ); $replacements = array( $name, $_SERVER['PHP_SELF'].' '.$name ); return str_replace($placeholders, $replacements, $this->getHelp()); } /** * Sets the aliases for the command. * * @param array $aliases An array of aliases for the command * * @return Command The current instance * * @throws \InvalidArgumentException When an alias is invalid * * @api */ public function setAliases($aliases) { foreach ($aliases as $alias) { $this->validateName($alias); } $this->aliases = $aliases; return $this; } /** * Returns the aliases for the command. * * @return array An array of aliases for the command * * @api */ public function getAliases() { return $this->aliases; } /** * Returns the synopsis for the command. * * @return string The synopsis */ public function getSynopsis() { if (null === $this->synopsis) { $this->synopsis = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis())); } return $this->synopsis; } /** * Gets a helper instance by name. * * @param string $name The helper name * * @return mixed The helper value * * @throws \InvalidArgumentException if the helper is not defined * * @api */ public function getHelper($name) { return $this->helperSet->get($name); } /** * Returns a text representation of the command. * * @return string A string representing the command * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asText() { $descriptor = new TextDescriptor(); $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); $descriptor->describe($output, $this, array('raw_output' => true)); return $output->fetch(); } /** * Returns an XML representation of the command. * * @param Boolean $asDom Whether to return a DOM or an XML string * * @return string|\DOMDocument An XML string representing the command * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asXml($asDom = false) { $descriptor = new XmlDescriptor(); if ($asDom) { return $descriptor->getCommandDocument($this); } $output = new BufferedOutput(); $descriptor->describe($output, $this); return $output->fetch(); } /** * Validates a command name. * * It must be non-empty and parts can optionally be separated by ":". * * @param string $name * * @throws \InvalidArgumentException When the name is invalid */ private function validateName($name) { if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) { throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); } } } PK] x Console/Command/ListCommand.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Helper\DescriptorHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputDefinition; /** * ListCommand displays the list of all available commands for the application. * * @author Fabien Potencier */ class ListCommand extends Command { /** * {@inheritdoc} */ protected function configure() { $this ->setName('list') ->setDefinition($this->createDefinition()) ->setDescription('Lists commands') ->setHelp(<<%command.name% command lists all commands: php %command.full_name% You can also display the commands for a specific namespace: php %command.full_name% test You can also output the information in other formats by using the --format option: php %command.full_name% --format=xml It's also possible to get raw list of commands (useful for embedding command runner): php %command.full_name% --raw EOF ) ; } /** * {@inheritdoc} */ public function getNativeDefinition() { return $this->createDefinition(); } /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { if ($input->getOption('xml')) { $input->setOption('format', 'xml'); } $helper = new DescriptorHelper(); $helper->describe($output, $this->getApplication(), array( 'format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), 'namespace' => $input->getArgument('namespace'), )); } /** * {@inheritdoc} */ private function createDefinition() { return new InputDefinition(array( new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats', 'txt'), )); } } PK]hrf f $Console/Tester/ApplicationTester.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tester; use Symfony\Component\Console\Application; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\StreamOutput; /** * Eases the testing of console applications. * * When testing an application, don't forget to disable the auto exit flag: * * $application = new Application(); * $application->setAutoExit(false); * * @author Fabien Potencier */ class ApplicationTester { private $application; private $input; private $output; private $statusCode; /** * Constructor. * * @param Application $application An Application instance to test. */ public function __construct(Application $application) { $this->application = $application; } /** * Executes the application. * * Available options: * * * interactive: Sets the input interactive flag * * decorated: Sets the output decorated flag * * verbosity: Sets the output verbosity flag * * @param array $input An array of arguments and options * @param array $options An array of options * * @return integer The command exit code */ public function run(array $input, $options = array()) { $this->input = new ArrayInput($input); if (isset($options['interactive'])) { $this->input->setInteractive($options['interactive']); } $this->output = new StreamOutput(fopen('php://memory', 'w', false)); if (isset($options['decorated'])) { $this->output->setDecorated($options['decorated']); } if (isset($options['verbosity'])) { $this->output->setVerbosity($options['verbosity']); } return $this->statusCode = $this->application->run($this->input, $this->output); } /** * Gets the display returned by the last execution of the application. * * @param Boolean $normalize Whether to normalize end of lines to \n or not * * @return string The display */ public function getDisplay($normalize = false) { rewind($this->output->getStream()); $display = stream_get_contents($this->output->getStream()); if ($normalize) { $display = str_replace(PHP_EOL, "\n", $display); } return $display; } /** * Gets the input instance used by the last execution of the application. * * @return InputInterface The current input instance */ public function getInput() { return $this->input; } /** * Gets the output instance used by the last execution of the application. * * @return OutputInterface The current output instance */ public function getOutput() { return $this->output; } /** * Gets the status code returned by the last execution of the application. * * @return integer The status code */ public function getStatusCode() { return $this->statusCode; } } PK]~H(R Console/Tester/CommandTester.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tester; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Eases the testing of console commands. * * @author Fabien Potencier */ class CommandTester { private $command; private $input; private $output; private $statusCode; /** * Constructor. * * @param Command $command A Command instance to test. */ public function __construct(Command $command) { $this->command = $command; } /** * Executes the command. * * Available options: * * * interactive: Sets the input interactive flag * * decorated: Sets the output decorated flag * * verbosity: Sets the output verbosity flag * * @param array $input An array of arguments and options * @param array $options An array of options * * @return integer The command exit code */ public function execute(array $input, array $options = array()) { // set the command name automatically if the application requires // this argument and no command name was passed if (!isset($input['command']) && (null !== $application = $this->command->getApplication()) && $application->getDefinition()->hasArgument('command') ) { $input['command'] = $this->command->getName(); } $this->input = new ArrayInput($input); if (isset($options['interactive'])) { $this->input->setInteractive($options['interactive']); } $this->output = new StreamOutput(fopen('php://memory', 'w', false)); if (isset($options['decorated'])) { $this->output->setDecorated($options['decorated']); } if (isset($options['verbosity'])) { $this->output->setVerbosity($options['verbosity']); } return $this->statusCode = $this->command->run($this->input, $this->output); } /** * Gets the display returned by the last execution of the command. * * @param Boolean $normalize Whether to normalize end of lines to \n or not * * @return string The display */ public function getDisplay($normalize = false) { rewind($this->output->getStream()); $display = stream_get_contents($this->output->getStream()); if ($normalize) { $display = str_replace(PHP_EOL, "\n", $display); } return $display; } /** * Gets the input instance used by the last execution of the command. * * @return InputInterface The current input instance */ public function getInput() { return $this->input; } /** * Gets the output instance used by the last execution of the command. * * @return OutputInterface The current output instance */ public function getOutput() { return $this->output; } /** * Gets the status code returned by the last execution of the application. * * @return integer The status code */ public function getStatusCode() { return $this->statusCode; } } PK].QQConsole/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * InputAwareInterface should be implemented by classes that depends on the * Console Input. * * @author Wouter J */ interface InputAwareInterface { /** * Sets the Console Input. * * @param InputInterface */ public function setInput(InputInterface $input); } PK]AM66 Console/Input/InputInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * InputInterface is the interface implemented by all input classes. * * @author Fabien Potencier */ interface InputInterface { /** * Returns the first argument from the raw parameters (not parsed). * * @return string The value of the first argument or null otherwise */ public function getFirstArgument(); /** * Returns true if the raw parameters (not parsed) contain a value. * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The values to look for in the raw parameters (can be an array) * * @return Boolean true if the value is contained in the raw parameters */ public function hasParameterOption($values); /** * Returns the value of a raw option (not parsed). * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found * * @return mixed The option value */ public function getParameterOption($values, $default = false); /** * Binds the current Input instance with the given arguments and options. * * @param InputDefinition $definition A InputDefinition instance */ public function bind(InputDefinition $definition); /** * Validates if arguments given are correct. * * Throws an exception when not enough arguments are given. * * @throws \RuntimeException */ public function validate(); /** * Returns all the given arguments merged with the default values. * * @return array */ public function getArguments(); /** * Gets argument by name. * * @param string $name The name of the argument * * @return mixed */ public function getArgument($name); /** * Sets an argument value by name. * * @param string $name The argument name * @param string $value The argument value * * @throws \InvalidArgumentException When argument given doesn't exist */ public function setArgument($name, $value); /** * Returns true if an InputArgument object exists by name or position. * * @param string|integer $name The InputArgument name or position * * @return Boolean true if the InputArgument object exists, false otherwise */ public function hasArgument($name); /** * Returns all the given options merged with the default values. * * @return array */ public function getOptions(); /** * Gets an option by name. * * @param string $name The name of the option * * @return mixed */ public function getOption($name); /** * Sets an option value by name. * * @param string $name The option name * @param string|boolean $value The option value * * @throws \InvalidArgumentException When option given doesn't exist */ public function setOption($name, $value); /** * Returns true if an InputOption object exists by name. * * @param string $name The InputOption name * * @return Boolean true if the InputOption object exists, false otherwise */ public function hasOption($name); /** * Is this input means interactive? * * @return Boolean */ public function isInteractive(); /** * Sets the input interactivity. * * @param Boolean $interactive If the input should be interactive */ public function setInteractive($interactive); } PK]1E(0(0!Console/Input/InputDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; if (!defined('JSON_UNESCAPED_UNICODE')) { define('JSON_UNESCAPED_SLASHES', 64); define('JSON_UNESCAPED_UNICODE', 256); } use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Output\BufferedOutput; /** * A InputDefinition represents a set of valid command line arguments and options. * * Usage: * * $definition = new InputDefinition(array( * new InputArgument('name', InputArgument::REQUIRED), * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), * )); * * @author Fabien Potencier * * @api */ class InputDefinition { private $arguments; private $requiredCount; private $hasAnArrayArgument = false; private $hasOptional; private $options; private $shortcuts; /** * Constructor. * * @param array $definition An array of InputArgument and InputOption instance * * @api */ public function __construct(array $definition = array()) { $this->setDefinition($definition); } /** * Sets the definition of the input. * * @param array $definition The definition array * * @api */ public function setDefinition(array $definition) { $arguments = array(); $options = array(); foreach ($definition as $item) { if ($item instanceof InputOption) { $options[] = $item; } else { $arguments[] = $item; } } $this->setArguments($arguments); $this->setOptions($options); } /** * Sets the InputArgument objects. * * @param InputArgument[] $arguments An array of InputArgument objects * * @api */ public function setArguments($arguments = array()) { $this->arguments = array(); $this->requiredCount = 0; $this->hasOptional = false; $this->hasAnArrayArgument = false; $this->addArguments($arguments); } /** * Adds an array of InputArgument objects. * * @param InputArgument[] $arguments An array of InputArgument objects * * @api */ public function addArguments($arguments = array()) { if (null !== $arguments) { foreach ($arguments as $argument) { $this->addArgument($argument); } } } /** * Adds an InputArgument object. * * @param InputArgument $argument An InputArgument object * * @throws \LogicException When incorrect argument is given * * @api */ public function addArgument(InputArgument $argument) { if (isset($this->arguments[$argument->getName()])) { throw new \LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName())); } if ($this->hasAnArrayArgument) { throw new \LogicException('Cannot add an argument after an array argument.'); } if ($argument->isRequired() && $this->hasOptional) { throw new \LogicException('Cannot add a required argument after an optional one.'); } if ($argument->isArray()) { $this->hasAnArrayArgument = true; } if ($argument->isRequired()) { ++$this->requiredCount; } else { $this->hasOptional = true; } $this->arguments[$argument->getName()] = $argument; } /** * Returns an InputArgument by name or by position. * * @param string|integer $name The InputArgument name or position * * @return InputArgument An InputArgument object * * @throws \InvalidArgumentException When argument given doesn't exist * * @api */ public function getArgument($name) { if (!$this->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; return $arguments[$name]; } /** * Returns true if an InputArgument object exists by name or position. * * @param string|integer $name The InputArgument name or position * * @return Boolean true if the InputArgument object exists, false otherwise * * @api */ public function hasArgument($name) { $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; return isset($arguments[$name]); } /** * Gets the array of InputArgument objects. * * @return InputArgument[] An array of InputArgument objects * * @api */ public function getArguments() { return $this->arguments; } /** * Returns the number of InputArguments. * * @return integer The number of InputArguments */ public function getArgumentCount() { return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments); } /** * Returns the number of required InputArguments. * * @return integer The number of required InputArguments */ public function getArgumentRequiredCount() { return $this->requiredCount; } /** * Gets the default values. * * @return array An array of default values */ public function getArgumentDefaults() { $values = array(); foreach ($this->arguments as $argument) { $values[$argument->getName()] = $argument->getDefault(); } return $values; } /** * Sets the InputOption objects. * * @param InputOption[] $options An array of InputOption objects * * @api */ public function setOptions($options = array()) { $this->options = array(); $this->shortcuts = array(); $this->addOptions($options); } /** * Adds an array of InputOption objects. * * @param InputOption[] $options An array of InputOption objects * * @api */ public function addOptions($options = array()) { foreach ($options as $option) { $this->addOption($option); } } /** * Adds an InputOption object. * * @param InputOption $option An InputOption object * * @throws \LogicException When option given already exist * * @api */ public function addOption(InputOption $option) { if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { throw new \LogicException(sprintf('An option named "%s" already exists.', $option->getName())); } if ($option->getShortcut()) { foreach (explode('|', $option->getShortcut()) as $shortcut) { if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) { throw new \LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut)); } } } $this->options[$option->getName()] = $option; if ($option->getShortcut()) { foreach (explode('|', $option->getShortcut()) as $shortcut) { $this->shortcuts[$shortcut] = $option->getName(); } } } /** * Returns an InputOption by name. * * @param string $name The InputOption name * * @return InputOption A InputOption object * * @throws \InvalidArgumentException When option given doesn't exist * * @api */ public function getOption($name) { if (!$this->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); } return $this->options[$name]; } /** * Returns true if an InputOption object exists by name. * * @param string $name The InputOption name * * @return Boolean true if the InputOption object exists, false otherwise * * @api */ public function hasOption($name) { return isset($this->options[$name]); } /** * Gets the array of InputOption objects. * * @return InputOption[] An array of InputOption objects * * @api */ public function getOptions() { return $this->options; } /** * Returns true if an InputOption object exists by shortcut. * * @param string $name The InputOption shortcut * * @return Boolean true if the InputOption object exists, false otherwise */ public function hasShortcut($name) { return isset($this->shortcuts[$name]); } /** * Gets an InputOption by shortcut. * * @param string $shortcut the Shortcut name * * @return InputOption An InputOption object */ public function getOptionForShortcut($shortcut) { return $this->getOption($this->shortcutToName($shortcut)); } /** * Gets an array of default values. * * @return array An array of all default values */ public function getOptionDefaults() { $values = array(); foreach ($this->options as $option) { $values[$option->getName()] = $option->getDefault(); } return $values; } /** * Returns the InputOption name given a shortcut. * * @param string $shortcut The shortcut * * @return string The InputOption name * * @throws \InvalidArgumentException When option given does not exist */ private function shortcutToName($shortcut) { if (!isset($this->shortcuts[$shortcut])) { throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); } return $this->shortcuts[$shortcut]; } /** * Gets the synopsis. * * @return string The synopsis */ public function getSynopsis() { $elements = array(); foreach ($this->getOptions() as $option) { $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName()); } foreach ($this->getArguments() as $argument) { $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : '')); if ($argument->isArray()) { $elements[] = sprintf('... [%sN]', $argument->getName()); } } return implode(' ', $elements); } /** * Returns a textual representation of the InputDefinition. * * @return string A string representing the InputDefinition * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asText() { $descriptor = new TextDescriptor(); $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); $descriptor->describe($output, $this, array('raw_output' => true)); return $output->fetch(); } /** * Returns an XML representation of the InputDefinition. * * @param Boolean $asDom Whether to return a DOM or an XML string * * @return string|\DOMDocument An XML string representing the InputDefinition * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asXml($asDom = false) { $descriptor = new XmlDescriptor(); if ($asDom) { return $descriptor->getInputDefinitionDocument($this); } $output = new BufferedOutput(); $descriptor->describe($output, $this); return $output->fetch(); } } PK]p%%Console/Input/ArrayInput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * ArrayInput represents an input provided as an array. * * Usage: * * $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar')); * * @author Fabien Potencier * * @api */ class ArrayInput extends Input { private $parameters; /** * Constructor. * * @param array $parameters An array of parameters * @param InputDefinition $definition A InputDefinition instance * * @api */ public function __construct(array $parameters, InputDefinition $definition = null) { $this->parameters = $parameters; parent::__construct($definition); } /** * Returns the first argument from the raw parameters (not parsed). * * @return string The value of the first argument or null otherwise */ public function getFirstArgument() { foreach ($this->parameters as $key => $value) { if ($key && '-' === $key[0]) { continue; } return $value; } } /** * Returns true if the raw parameters (not parsed) contain a value. * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The values to look for in the raw parameters (can be an array) * * @return Boolean true if the value is contained in the raw parameters */ public function hasParameterOption($values) { $values = (array) $values; foreach ($this->parameters as $k => $v) { if (!is_int($k)) { $v = $k; } if (in_array($v, $values)) { return true; } } return false; } /** * Returns the value of a raw option (not parsed). * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found * * @return mixed The option value */ public function getParameterOption($values, $default = false) { $values = (array) $values; foreach ($this->parameters as $k => $v) { if (is_int($k) && in_array($v, $values)) { return true; } elseif (in_array($k, $values)) { return $v; } } return $default; } /** * Returns a stringified representation of the args passed to the command * * @return string */ public function __toString() { $params = array(); foreach ($this->parameters as $param => $val) { if ($param && '-' === $param[0]) { $params[] = $param . ('' != $val ? '='.$this->escapeToken($val) : ''); } else { $params[] = $this->escapeToken($val); } } return implode(' ', $params); } /** * Processes command line arguments. */ protected function parse() { foreach ($this->parameters as $key => $value) { if (0 === strpos($key, '--')) { $this->addLongOption(substr($key, 2), $value); } elseif ('-' === $key[0]) { $this->addShortOption(substr($key, 1), $value); } else { $this->addArgument($key, $value); } } } /** * Adds a short option value. * * @param string $shortcut The short option key * @param mixed $value The value for the option * * @throws \InvalidArgumentException When option given doesn't exist */ private function addShortOption($shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); } $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); } /** * Adds a long option value. * * @param string $name The long option key * @param mixed $value The value for the option * * @throws \InvalidArgumentException When option given doesn't exist * @throws \InvalidArgumentException When a required value is missing */ private function addLongOption($name, $value) { if (!$this->definition->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); } $option = $this->definition->getOption($name); if (null === $value) { if ($option->isValueRequired()) { throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name)); } $value = $option->isValueOptional() ? $option->getDefault() : true; } $this->options[$name] = $value; } /** * Adds an argument value. * * @param string $name The argument name * @param mixed $value The value for the argument * * @throws \InvalidArgumentException When argument given doesn't exist */ private function addArgument($name, $value) { if (!$this->definition->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } $this->arguments[$name] = $value; } } PK]Q))Console/Input/ArgvInput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * ArgvInput represents an input coming from the CLI arguments. * * Usage: * * $input = new ArgvInput(); * * By default, the `$_SERVER['argv']` array is used for the input values. * * This can be overridden by explicitly passing the input values in the constructor: * * $input = new ArgvInput($_SERVER['argv']); * * If you pass it yourself, don't forget that the first element of the array * is the name of the running application. * * When passing an argument to the constructor, be sure that it respects * the same rules as the argv one. It's almost always better to use the * `StringInput` when you want to provide your own input. * * @author Fabien Potencier * * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 * * @api */ class ArgvInput extends Input { private $tokens; private $parsed; /** * Constructor. * * @param array $argv An array of parameters from the CLI (in the argv format) * @param InputDefinition $definition A InputDefinition instance * * @api */ public function __construct(array $argv = null, InputDefinition $definition = null) { if (null === $argv) { $argv = $_SERVER['argv']; } // strip the application name array_shift($argv); $this->tokens = $argv; parent::__construct($definition); } protected function setTokens(array $tokens) { $this->tokens = $tokens; } /** * Processes command line arguments. */ protected function parse() { $parseOptions = true; $this->parsed = $this->tokens; while (null !== $token = array_shift($this->parsed)) { if ($parseOptions && '' == $token) { $this->parseArgument($token); } elseif ($parseOptions && '--' == $token) { $parseOptions = false; } elseif ($parseOptions && 0 === strpos($token, '--')) { $this->parseLongOption($token); } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { $this->parseShortOption($token); } else { $this->parseArgument($token); } } } /** * Parses a short option. * * @param string $token The current token. */ private function parseShortOption($token) { $name = substr($token, 1); if (strlen($name) > 1) { if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { // an option with a value (with no space) $this->addShortOption($name[0], substr($name, 1)); } else { $this->parseShortOptionSet($name); } } else { $this->addShortOption($name, null); } } /** * Parses a short option set. * * @param string $name The current token * * @throws \RuntimeException When option given doesn't exist */ private function parseShortOptionSet($name) { $len = strlen($name); for ($i = 0; $i < $len; $i++) { if (!$this->definition->hasShortcut($name[$i])) { throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i])); } $option = $this->definition->getOptionForShortcut($name[$i]); if ($option->acceptValue()) { $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); break; } else { $this->addLongOption($option->getName(), null); } } } /** * Parses a long option. * * @param string $token The current token */ private function parseLongOption($token) { $name = substr($token, 2); if (false !== $pos = strpos($name, '=')) { $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1)); } else { $this->addLongOption($name, null); } } /** * Parses an argument. * * @param string $token The current token * * @throws \RuntimeException When too many arguments are given */ private function parseArgument($token) { $c = count($this->arguments); // if input is expecting another argument, add it if ($this->definition->hasArgument($c)) { $arg = $this->definition->getArgument($c); $this->arguments[$arg->getName()] = $arg->isArray()? array($token) : $token; // if last argument isArray(), append token to last argument } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { $arg = $this->definition->getArgument($c - 1); $this->arguments[$arg->getName()][] = $token; // unexpected argument } else { throw new \RuntimeException('Too many arguments.'); } } /** * Adds a short option value. * * @param string $shortcut The short option key * @param mixed $value The value for the option * * @throws \RuntimeException When option given doesn't exist */ private function addShortOption($shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); } $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); } /** * Adds a long option value. * * @param string $name The long option key * @param mixed $value The value for the option * * @throws \RuntimeException When option given doesn't exist */ private function addLongOption($name, $value) { if (!$this->definition->hasOption($name)) { throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name)); } $option = $this->definition->getOption($name); // Convert false values (from a previous call to substr()) to null if (false === $value) { $value = null; } if (null !== $value && !$option->acceptValue()) { throw new \RuntimeException(sprintf('The "--%s" option does not accept a value.', $name, $value)); } if (null === $value && $option->acceptValue() && count($this->parsed)) { // if option accepts an optional or mandatory argument // let's see if there is one provided $next = array_shift($this->parsed); if (isset($next[0]) && '-' !== $next[0]) { $value = $next; } elseif (empty($next)) { $value = ''; } else { array_unshift($this->parsed, $next); } } if (null === $value) { if ($option->isValueRequired()) { throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name)); } if (!$option->isArray()) { $value = $option->isValueOptional() ? $option->getDefault() : true; } } if ($option->isArray()) { $this->options[$name][] = $value; } else { $this->options[$name] = $value; } } /** * Returns the first argument from the raw parameters (not parsed). * * @return string The value of the first argument or null otherwise */ public function getFirstArgument() { foreach ($this->tokens as $token) { if ($token && '-' === $token[0]) { continue; } return $token; } } /** * Returns true if the raw parameters (not parsed) contain a value. * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * * @return Boolean true if the value is contained in the raw parameters */ public function hasParameterOption($values) { $values = (array) $values; foreach ($this->tokens as $token) { foreach ($values as $value) { if ($token === $value || 0 === strpos($token, $value.'=')) { return true; } } } return false; } /** * Returns the value of a raw option (not parsed). * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found * * @return mixed The option value */ public function getParameterOption($values, $default = false) { $values = (array) $values; $tokens = $this->tokens; while ($token = array_shift($tokens)) { foreach ($values as $value) { if ($token === $value || 0 === strpos($token, $value.'=')) { if (false !== $pos = strpos($token, '=')) { return substr($token, $pos + 1); } return array_shift($tokens); } } } return $default; } /** * Returns a stringified representation of the args passed to the command * * @return string */ public function __toString() { $self = $this; $tokens = array_map(function ($token) use ($self) { if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { return $match[1] . $self->escapeToken($match[2]); } if ($token && $token[0] !== '-') { return $self->escapeToken($token); } return $token; }, $this->tokens); return implode(' ', $tokens); } } PK]OVVConsole/Input/InputOption.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * Represents a command line option. * * @author Fabien Potencier * * @api */ class InputOption { const VALUE_NONE = 1; const VALUE_REQUIRED = 2; const VALUE_OPTIONAL = 4; const VALUE_IS_ARRAY = 8; private $name; private $shortcut; private $mode; private $default; private $description; /** * Constructor. * * @param string $name The option name * @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts * @param integer $mode The option mode: One of the VALUE_* constants * @param string $description A description text * @param mixed $default The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE) * * @throws \InvalidArgumentException If option mode is invalid or incompatible * * @api */ public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null) { if (0 === strpos($name, '--')) { $name = substr($name, 2); } if (empty($name)) { throw new \InvalidArgumentException('An option name cannot be empty.'); } if (empty($shortcut)) { $shortcut = null; } if (null !== $shortcut) { if (is_array($shortcut)) { $shortcut = implode('|', $shortcut); } $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); $shortcuts = array_filter($shortcuts); $shortcut = implode('|', $shortcuts); if (empty($shortcut)) { throw new \InvalidArgumentException('An option shortcut cannot be empty.'); } } if (null === $mode) { $mode = self::VALUE_NONE; } elseif (!is_int($mode) || $mode > 15 || $mode < 1) { throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); } $this->name = $name; $this->shortcut = $shortcut; $this->mode = $mode; $this->description = $description; if ($this->isArray() && !$this->acceptValue()) { throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); } $this->setDefault($default); } /** * Returns the option shortcut. * * @return string The shortcut */ public function getShortcut() { return $this->shortcut; } /** * Returns the option name. * * @return string The name */ public function getName() { return $this->name; } /** * Returns true if the option accepts a value. * * @return Boolean true if value mode is not self::VALUE_NONE, false otherwise */ public function acceptValue() { return $this->isValueRequired() || $this->isValueOptional(); } /** * Returns true if the option requires a value. * * @return Boolean true if value mode is self::VALUE_REQUIRED, false otherwise */ public function isValueRequired() { return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); } /** * Returns true if the option takes an optional value. * * @return Boolean true if value mode is self::VALUE_OPTIONAL, false otherwise */ public function isValueOptional() { return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); } /** * Returns true if the option can take multiple values. * * @return Boolean true if mode is self::VALUE_IS_ARRAY, false otherwise */ public function isArray() { return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); } /** * Sets the default value. * * @param mixed $default The default value * * @throws \LogicException When incorrect default value is given */ public function setDefault($default = null) { if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { throw new \LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.'); } if ($this->isArray()) { if (null === $default) { $default = array(); } elseif (!is_array($default)) { throw new \LogicException('A default value for an array option must be an array.'); } } $this->default = $this->acceptValue() ? $default : false; } /** * Returns the default value. * * @return mixed The default value */ public function getDefault() { return $this->default; } /** * Returns the description text. * * @return string The description text */ public function getDescription() { return $this->description; } /** * Checks whether the given option equals this one * * @param InputOption $option option to compare * @return Boolean */ public function equals(InputOption $option) { return $option->getName() === $this->getName() && $option->getShortcut() === $this->getShortcut() && $option->getDefault() === $this->getDefault() && $option->isArray() === $this->isArray() && $option->isValueRequired() === $this->isValueRequired() && $option->isValueOptional() === $this->isValueOptional() ; } } PK]' Console/Input/InputArgument.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * Represents a command line argument. * * @author Fabien Potencier * * @api */ class InputArgument { const REQUIRED = 1; const OPTIONAL = 2; const IS_ARRAY = 4; private $name; private $mode; private $default; private $description; /** * Constructor. * * @param string $name The argument name * @param integer $mode The argument mode: self::REQUIRED or self::OPTIONAL * @param string $description A description text * @param mixed $default The default value (for self::OPTIONAL mode only) * * @throws \InvalidArgumentException When argument mode is not valid * * @api */ public function __construct($name, $mode = null, $description = '', $default = null) { if (null === $mode) { $mode = self::OPTIONAL; } elseif (!is_int($mode) || $mode > 7 || $mode < 1) { throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); } $this->name = $name; $this->mode = $mode; $this->description = $description; $this->setDefault($default); } /** * Returns the argument name. * * @return string The argument name */ public function getName() { return $this->name; } /** * Returns true if the argument is required. * * @return Boolean true if parameter mode is self::REQUIRED, false otherwise */ public function isRequired() { return self::REQUIRED === (self::REQUIRED & $this->mode); } /** * Returns true if the argument can take multiple values. * * @return Boolean true if mode is self::IS_ARRAY, false otherwise */ public function isArray() { return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); } /** * Sets the default value. * * @param mixed $default The default value * * @throws \LogicException When incorrect default value is given */ public function setDefault($default = null) { if (self::REQUIRED === $this->mode && null !== $default) { throw new \LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.'); } if ($this->isArray()) { if (null === $default) { $default = array(); } elseif (!is_array($default)) { throw new \LogicException('A default value for an array argument must be an array.'); } } $this->default = $default; } /** * Returns the default value. * * @return mixed The default value */ public function getDefault() { return $this->default; } /** * Returns the description text. * * @return string The description text */ public function getDescription() { return $this->description; } } PK]gm(Console/Input/Input.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * Input is the base class for all concrete Input classes. * * Three concrete classes are provided by default: * * * `ArgvInput`: The input comes from the CLI arguments (argv) * * `StringInput`: The input is provided as a string * * `ArrayInput`: The input is provided as an array * * @author Fabien Potencier */ abstract class Input implements InputInterface { /** * @var InputDefinition */ protected $definition; protected $options = array(); protected $arguments = array(); protected $interactive = true; /** * Constructor. * * @param InputDefinition $definition A InputDefinition instance */ public function __construct(InputDefinition $definition = null) { if (null === $definition) { $this->definition = new InputDefinition(); } else { $this->bind($definition); $this->validate(); } } /** * Binds the current Input instance with the given arguments and options. * * @param InputDefinition $definition A InputDefinition instance */ public function bind(InputDefinition $definition) { $this->arguments = array(); $this->options = array(); $this->definition = $definition; $this->parse(); } /** * Processes command line arguments. */ abstract protected function parse(); /** * Validates the input. * * @throws \RuntimeException When not enough arguments are given */ public function validate() { if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) { throw new \RuntimeException('Not enough arguments.'); } } /** * Checks if the input is interactive. * * @return Boolean Returns true if the input is interactive */ public function isInteractive() { return $this->interactive; } /** * Sets the input interactivity. * * @param Boolean $interactive If the input should be interactive */ public function setInteractive($interactive) { $this->interactive = (Boolean) $interactive; } /** * Returns the argument values. * * @return array An array of argument values */ public function getArguments() { return array_merge($this->definition->getArgumentDefaults(), $this->arguments); } /** * Returns the argument value for a given argument name. * * @param string $name The argument name * * @return mixed The argument value * * @throws \InvalidArgumentException When argument given doesn't exist */ public function getArgument($name) { if (!$this->definition->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault(); } /** * Sets an argument value by name. * * @param string $name The argument name * @param string $value The argument value * * @throws \InvalidArgumentException When argument given doesn't exist */ public function setArgument($name, $value) { if (!$this->definition->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } $this->arguments[$name] = $value; } /** * Returns true if an InputArgument object exists by name or position. * * @param string|integer $name The InputArgument name or position * * @return Boolean true if the InputArgument object exists, false otherwise */ public function hasArgument($name) { return $this->definition->hasArgument($name); } /** * Returns the options values. * * @return array An array of option values */ public function getOptions() { return array_merge($this->definition->getOptionDefaults(), $this->options); } /** * Returns the option value for a given option name. * * @param string $name The option name * * @return mixed The option value * * @throws \InvalidArgumentException When option given doesn't exist */ public function getOption($name) { if (!$this->definition->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); } return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); } /** * Sets an option value by name. * * @param string $name The option name * @param string|boolean $value The option value * * @throws \InvalidArgumentException When option given doesn't exist */ public function setOption($name, $value) { if (!$this->definition->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); } $this->options[$name] = $value; } /** * Returns true if an InputOption object exists by name. * * @param string $name The InputOption name * * @return Boolean true if the InputOption object exists, false otherwise */ public function hasOption($name) { return $this->definition->hasOption($name); } /** * Escapes a token through escapeshellarg if it contains unsafe chars * * @param string $token * * @return string */ public function escapeToken($token) { return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); } } PK]΂= Console/Input/StringInput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * StringInput represents an input provided as a string. * * Usage: * * $input = new StringInput('foo --bar="foobar"'); * * @author Fabien Potencier * * @api */ class StringInput extends ArgvInput { const REGEX_STRING = '([^\s]+?)(?:\s|(?setTokens($this->tokenize($input)); if (null !== $definition) { $this->bind($definition); } } /** * Tokenizes a string. * * @param string $input The input to tokenize * * @return array An array of tokens * * @throws \InvalidArgumentException When unable to parse input (should never happen) */ private function tokenize($input) { $tokens = array(); $length = strlen($input); $cursor = 0; while ($cursor < $length) { if (preg_match('/\s+/A', $input, $match, null, $cursor)) { } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) { $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2))); } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) { $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2)); } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) { $tokens[] = stripcslashes($match[1]); } else { // should never happen // @codeCoverageIgnoreStart throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10))); // @codeCoverageIgnoreEnd } $cursor += strlen($match[0]); } return $tokens; } } PK]Gk !Validator/ConstraintValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Base class for constraint validators * * @author Bernhard Schussek * * @api */ abstract class ConstraintValidator implements ConstraintValidatorInterface { /** * @var ExecutionContextInterface */ protected $context; /** * {@inheritDoc} */ public function initialize(ExecutionContextInterface $context) { $this->context = $context; } } PK]-tZMZM2Validator/Resources/translations/validators.ru.xlfnu[ This value should be false. Значение должно быть ложным. This value should be true. Значение должно быть истинным. This value should be of type {{ type }}. Тип значения должен быть {{ type }}. This value should be blank. Значение должно быть пустым. The value you selected is not a valid choice. Выбранное Вами значение недопустимо. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Вы должны выбрать хотя бы {{ limit }} вариант.|Вы должны выбрать хотя бы {{ limit }} варианта.|Вы должны выбрать хотя бы {{ limit }} вариантов. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Вы должны выбрать не более чем {{ limit }} вариант.|Вы должны выбрать не более чем {{ limit }} варианта.|Вы должны выбрать не более чем {{ limit }} вариантов. One or more of the given values is invalid. Одно или несколько заданных значений недопустимо. The fields {{ fields }} were not expected. Поля {{ fields }} не ожидались. The fields {{ fields }} are missing. Поля {{ fields }} отсутствуют. This value is not a valid date. Значение не является правильной датой. This value is not a valid datetime. Значение даты и времени недопустимо. This value is not a valid email address. Значение адреса электронной почты недопустимо. The file could not be found. Файл не может быть найден. The file is not readable. Файл не может быть прочитан. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файл слишком большой ({{ size }} {{ suffix }}). Максимально допустимый размер {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. MIME-тип файла недопустим ({{ type }}). Допустимы MIME-типы файлов {{ types }}. This value should be {{ limit }} or less. Значение должно быть {{ limit }} или меньше. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Значение слишком длинное. Должно быть равно {{ limit }} символу или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше. This value should be {{ limit }} or more. Значение должно быть {{ limit }} или больше. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Значение слишком короткое. Должно быть равно {{ limit }} символу или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше. This value should not be blank. Значение не должно быть пустым. This value should not be null. Значение не должно быть null. This value should be null. Значение должно быть null. This value is not valid. Значение недопустимо. This value is not a valid time. Значение времени недопустимо. This value is not a valid URL. Значение не является допустимым URL. The two values should be equal. Оба значения должны быть одинаковыми. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файл слишком большой. Максимально допустимый размер {{ limit }} {{ suffix }}. The file is too large. Файл слишком большой. The file could not be uploaded. Файл не может быть загружен. This value should be a valid number. Значение должно быть числом. This value is not a valid country. Значение не является допустимой страной. This file is not a valid image. Файл не является допустимым форматом изображения. This is not a valid IP address. Значение не является допустимым IP адресом. This value is not a valid language. Значение не является допустимым языком. This value is not a valid locale. Значение не является допустимой локалью. This value is already used. Это значение уже используется. The size of the image could not be detected. Не удалось определить размер изображения. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Ширина изображения слишком велика ({{ width }}px). Максимально допустимая ширина {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Ширина изображения слишком мала ({{ width }}px). Минимально допустимая ширина {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Высота изображения слишком велика ({{ height }}px). Максимально допустимая высота {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Высота изображения слишком мала ({{ height }}px). Минимально допустимая высота {{ min_height }}px. This value should be the user current password. Значение должно быть текущим паролем пользователя. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Значение должно быть равно {{ limit }} символу.|Значение должно быть равно {{ limit }} символам.|Значение должно быть равно {{ limit }} символам. The file was only partially uploaded. Файл был загружен только частично. No file was uploaded. Файл не был загружен. No temporary folder was configured in php.ini. Не настроена временная директория в php.ini. Cannot write temporary file to disk. Невозможно записать временный файл на диск. A PHP extension caused the upload to fail. Расширение PHP вызвало ошибку при загрузке. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Эта коллекция должна содержать {{ limit }} элемент или больше.|Эта коллекция должна содержать {{ limit }} элемента или больше.|Эта коллекция должна содержать {{ limit }} элементов или больше. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Эта коллекция должна содержать {{ limit }} элемент или меньше.|Эта коллекция должна содержать {{ limit }} элемента или меньше.|Эта коллекция должна содержать {{ limit }} элементов или меньше. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Эта коллекция должна содержать ровно {{ limit }} элемент.|Эта коллекция должна содержать ровно {{ limit }} элемента.|Эта коллекция должна содержать ровно {{ limit }} элементов. Invalid card number. Неверный номер карты. Unsupported card type or invalid card number. Неподдерживаемый тип или неверный номер карты. This is not a valid International Bank Account Number (IBAN). Значение не является допустимым международным номером банковского счета (IBAN). This value is not a valid ISBN-10. Значение имеет неверный формат ISBN-10. This value is not a valid ISBN-13. Значение имеет неверный формат ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Значение не соответствует форматам ISBN-10 и ISBN-13. This value is not a valid ISSN. Значение не соответствует формату ISSN. This value is not a valid currency. Некорректный формат валюты. This value should be equal to {{ compared_value }}. Значение должно быть равно {{ compared_value }}. This value should be greater than {{ compared_value }}. Значение должно быть больше чем {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Значение должно быть больше или равно {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Значение должно быть идентичным {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Значение должно быть меньше чем {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Значение должно быть меньше или равно {{ compared_value }}. This value should not be equal to {{ compared_value }}. Значение не должно быть равно {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Значение не должно быть идентичным {{ compared_value_type }} {{ compared_value }}. PK]b@@2Validator/Resources/translations/validators.pt.xlfnu[ This value should be false. Este valor deveria ser falso. This value should be true. Este valor deveria ser verdadeiro. This value should be of type {{ type }}. Este valor deveria ser do tipo {{ type }}. This value should be blank. Este valor deveria ser vazio. The value you selected is not a valid choice. O valor selecionado não é uma opção válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Você deveria selecionar {{ limit }} opção no mínimo.|Você deveria selecionar {{ limit }} opções no mínimo. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Você deve selecionar, no máximo {{ limit }} opção.|Você deve selecionar, no máximo {{ limit }} opções. One or more of the given values is invalid. Um ou mais dos valores introduzidos não são válidos. The fields {{ fields }} were not expected. Os campos {{ fields }} não eram esperados. The fields {{ fields }} are missing. Os campos {{ fields }} estão ausentes. This value is not a valid date. Este valor não é uma data válida. This value is not a valid datetime. Este valor não é uma data-hora válida. This value is not a valid email address. Este valor não é um endereço de e-mail válido. The file could not be found. O arquivo não pôde ser encontrado. The file is not readable. O arquivo não pôde ser lido. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é de {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}. This value should be {{ limit }} or less. Este valor deveria ser {{ limit }} ou menor. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. O valor é muito longo. Deveria ter {{ limit }} caracteres ou menos. This value should be {{ limit }} or more. Este valor deveria ser {{ limit }} ou mais. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. O valor é muito curto. Deveria de ter {{ limit }} caractere ou mais.|O valor é muito curto. Deveria de ter {{ limit }} caracteres ou mais. This value should not be blank. Este valor não deveria ser branco/vazio. This value should not be null. Este valor não deveria ser nulo. This value should be null. Este valor deveria ser nulo. This value is not valid. Este valor não é válido. This value is not a valid time. Este valor não é uma hora válida. This value is not a valid URL. Este valor não é um URL válido. The two values should be equal. Os dois valores deveriam ser iguais. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}. The file is too large. O ficheiro é muito grande. The file could not be uploaded. Não foi possível carregar o ficheiro. This value should be a valid number. Este valor deveria de ser um número válido. This file is not a valid image. Este ficheiro não é uma imagem. This is not a valid IP address. Este endereço de IP não é válido. This value is not a valid language. Este valor não é uma linguagem válida. This value is not a valid locale. Este valor não é um 'locale' válido. This value is not a valid country. Este valor não é um País válido. This value is already used. Este valor já está a ser usado. The size of the image could not be detected. O tamanho da imagem não foi detetado. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A largura da imagem ({{ width }}px) é muito grande. A largura máxima da imagem é: {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A largura da imagem ({{ width }}px) é muito pequena. A largura miníma da imagem é de: {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A altura da imagem ({{ height }}px) é muito grande. A altura máxima da imagem é de: {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A altura da imagem ({{ height }}px) é muito pequena. A altura miníma da imagem é de: {{ min_height }}px. This value should be the user current password. Este valor deveria de ser a password atual do utilizador. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor tem de ter exatamente {{ limit }} carateres. The file was only partially uploaded. Só foi enviado parte do ficheiro. No file was uploaded. Nenhum ficheiro foi enviado. No temporary folder was configured in php.ini. Não existe nenhum directório temporária configurado no ficheiro php.ini. Cannot write temporary file to disk. Não foi possível escrever ficheiros temporários no disco. A PHP extension caused the upload to fail. Uma extensão PHP causou a falha no envio. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos. Invalid card number. Número de cartão inválido. Unsupported card type or invalid card number. Tipo de cartão não suportado ou número de cartão inválido. This is not a valid International Bank Account Number (IBAN). Este não é um Número Internacional de Conta Bancária (IBAN) válido. This value is not a valid ISBN-10. Este valor não é um ISBN-10 válido. This value is not a valid ISBN-13. Este valor não é um ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor não é um ISBN-10 ou ISBN-13 válido. This value is not a valid ISSN. Este valor não é um ISSN válido. This value is not a valid currency. Este não é um valor monetário válido. This value should be equal to {{ compared_value }}. Este valor deve ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor deve ser superior a {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor deve ser igual ou superior a {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor deve ser inferior a {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor deve ser igual ou inferior a {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor não deve ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor não deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. PK]D#??2Validator/Resources/translations/validators.en.xlfnu[ This value should be false. This value should be false. This value should be true. This value should be true. This value should be of type {{ type }}. This value should be of type {{ type }}. This value should be blank. This value should be blank. The value you selected is not a valid choice. The value you selected is not a valid choice. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. One or more of the given values is invalid. One or more of the given values is invalid. The fields {{ fields }} were not expected. The fields {{ fields }} were not expected. The fields {{ fields }} are missing. The fields {{ fields }} are missing. This value is not a valid date. This value is not a valid date. This value is not a valid datetime. This value is not a valid datetime. This value is not a valid email address. This value is not a valid email address. The file could not be found. The file could not be found. The file is not readable. The file is not readable. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. This value should be {{ limit }} or less. This value should be {{ limit }} or less. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. This value should be {{ limit }} or more. This value should be {{ limit }} or more. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. This value should not be blank. This value should not be blank. This value should not be null. This value should not be null. This value should be null. This value should be null. This value is not valid. This value is not valid. This value is not a valid time. This value is not a valid time. This value is not a valid URL. This value is not a valid URL. The two values should be equal. The two values should be equal. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. The file is too large. The file is too large. The file could not be uploaded. The file could not be uploaded. This value should be a valid number. This value should be a valid number. This file is not a valid image. This file is not a valid image. This is not a valid IP address. This is not a valid IP address. This value is not a valid language. This value is not a valid language. This value is not a valid locale. This value is not a valid locale. This value is not a valid country. This value is not a valid country. This value is already used. This value is already used. The size of the image could not be detected. The size of the image could not be detected. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. This value should be the user current password. This value should be the user current password. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. The file was only partially uploaded. The file was only partially uploaded. No file was uploaded. No file was uploaded. No temporary folder was configured in php.ini. No temporary folder was configured in php.ini. Cannot write temporary file to disk. Cannot write temporary file to disk. A PHP extension caused the upload to fail. A PHP extension caused the upload to fail. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Invalid card number. Invalid card number. Unsupported card type or invalid card number. Unsupported card type or invalid card number. This is not a valid International Bank Account Number (IBAN). This is not a valid International Bank Account Number (IBAN). This value is not a valid ISBN-10. This value is not a valid ISBN-10. This value is not a valid ISBN-13. This value is not a valid ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. This value is not a valid ISSN. This value is not a valid ISSN. This value is not a valid currency. This value is not a valid currency. This value should be equal to {{ compared_value }}. This value should be equal to {{ compared_value }}. This value should be greater than {{ compared_value }}. This value should be greater than {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. This value should be less than {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. This value should not be equal to {{ compared_value }}. This value should not be equal to {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. PK]tý552Validator/Resources/translations/validators.he.xlfnu[ This value should be false. הערך צריך להיות שקר. This value should be true. הערך צריך להיות אמת. This value should be of type {{ type }}. הערך צריך להיות מסוג {{ type }}. This value should be blank. הערך צריך להיות ריק. The value you selected is not a valid choice. הערך שבחרת אינו חוקי. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. אתה צריך לבחור לפחות {{ limit }} אפשרויות.|אתה צריך לבחור לפחות {{ limit }} אפשרויות. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. אתה צריך לבחור לכל היותר {{ limit }} אפשרויות.|אתה צריך לבחור לכל היותר {{ limit }} אפשרויות. One or more of the given values is invalid. אחד או יותר מהערכים אינו חוקי. The fields {{ fields }} were not expected. השדות {{ fields }} לא היו צפויים. The fields {{ fields }} are missing. השדות {{ fields }} חסרים. This value is not a valid date. הערך אינו תאריך חוקי. This value is not a valid datetime. הערך אינו תאריך ושעה חוקיים. This value is not a valid email address. כתובת המייל אינה תקינה. The file could not be found. הקובץ לא נמצא. The file is not readable. לא ניתן לקרוא את הקובץ. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. הקובץ גדול מדי ({{ size }} {{ suffix }}). הגודל המרבי המותר הוא {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. סוג MIME של הקובץ אינו חוקי ({{ type }}). מותרים סוגי MIME {{ types }}. This value should be {{ limit }} or less. הערך צריל להכיל {{ limit }} תווים לכל היותר. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר.|הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר. This value should be {{ limit }} or more. הערך צריך להכיל {{ limit }} תווים לפחות. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות.|הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות. This value should not be blank. הערך לא אמור להיות ריק. This value should not be null. הערך לא אמור להיות ריק. This value should be null. הערך צריך להיות ריק. This value is not valid. הערך אינו חוקי. This value is not a valid time. הערך אינו זמן תקין. This value is not a valid URL. זאת אינה כתובת אתר תקינה. The two values should be equal. שני הערכים צריכים להיות שווים. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. הקובץ גדול מדי. הגודל המרבי המותר הוא {{ limit }} {{ suffix }}. The file is too large. הקובץ גדול מדי. The file could not be uploaded. לא ניתן לעלות את הקובץ. This value should be a valid number. הערך צריך להיות מספר חוקי. This file is not a valid image. הקובץ הזה אינו תמונה תקינה. This is not a valid IP address. זו אינה כתובת IP חוקית. This value is not a valid language. הערך אינו שפה חוקית. This value is not a valid locale. הערך אינו אזור תקף. This value is not a valid country. הערך אינו ארץ חוקית. This value is already used. הערך כבר בשימוש. The size of the image could not be detected. לא ניתן לקבוע את גודל התמונה. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. רוחב התמונה גדול מדי ({{ width }}px). הרוחב המקסימלי הוא {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. רוחב התמונה קטן מדי ({{ width }}px). הרוחב המינימלי הוא {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. גובה התמונה גדול מדי ({{ height }}px). הגובה המקסימלי הוא {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. גובה התמונה קטן מדי ({{ height }}px). הגובה המינימלי הוא {{ min_height }}px. This value should be the user current password. הערך צריך להיות סיסמת המשתמש הנוכחי. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. הערך צריך להיות בדיוק {{ limit }} תווים.|הערך צריך להיות בדיוק {{ limit }} תווים. The file was only partially uploaded. הקובץ הועלה באופן חלקי. No file was uploaded. הקובץ לא הועלה. No temporary folder was configured in php.ini. לא הוגדרה תיקייה זמנית ב php.ini. Cannot write temporary file to disk. לא ניתן לכתוב קובץ זמני לדיסק. A PHP extension caused the upload to fail. סיומת PHP גרם להעלאה להיכשל. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. האוסף אמור להכיל {{ limit }} אלמנטים או יותר.|האוסף אמור להכיל {{ limit }} אלמנטים או יותר. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. האוסף אמור להכיל {{ limit }} אלמנטים או פחות.|האוסף אמור להכיל {{ limit }} אלמנטים או פחות. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. האוסף צריך להכיל בדיוק {{ limit }} אלמנטים.|האוסף צריך להכיל בדיוק {{ limit }} אלמנטים. Invalid card number. מספר הכרטיס אינו חוקי. Unsupported card type or invalid card number. סוג הכרטיס אינו נתמך או לא חוקי. PK]D#"#"2Validator/Resources/translations/validators.mn.xlfnu[ This value should be false. Энэ утга буруу байх ёстой. This value should be true. Энэ утга үнэн байх ёстой. This value should be of type {{ type }}. Энэ утга {{ type }} -н төрөл байх ёстой. This value should be blank. Энэ утга хоосон байх ёстой. The value you selected is not a valid choice. Сонгосон утга буруу байна. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Хамгийн багадаа {{ limit }} утга сонгогдсон байх ёстой. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Хамгийн ихдээ {{ limit }} утга сонгогдох боломжтой. One or more of the given values is invalid. Өгөгдсөн нэг эсвэл нэгээс олон утга буруу байна. Талбарууд {{ fields }} зөвшөөрөгдөөгүй байна. {{ fields }}. The fields {{ fields }} are missing. {{ fields }} талбарууд дутуу байна. This value is not a valid date. Энэ утга буруу date төрөл байна . This value is not a valid datetime. Энэ утга буруу цаг төрөл байна. This value is not a valid email address. И-майл хаяг буруу байна. The file could not be found. Файл олдсонгүй. The file is not readable. Файл уншигдахуйц биш байна. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файл хэтэрхий том байна ({{ size }} {{ suffix }}). Зөвшөөрөгдөх дээд хэмжээ {{ limit }} {{ suffix }} байна. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Файлын MIME-төрөл нь буруу байна ({{ type }}). Зөвшөөрөгдөх MIME-төрлүүд {{ types }}. This value should be {{ limit }} or less. Энэ утга {{ limit }} юмуу эсвэл бага байна. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Энэ утга хэтэрхий урт байна. {{ limit }} тэмдэгтийн урттай юмуу эсвэл бага байна. This value should be {{ limit }} or more. Энэ утга {{ limit }} юмуу эсвэл их байна. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Энэ утга хэтэрхий богино байна. {{ limit }} тэмдэгт эсвэл их байна. This value should not be blank. Энэ утга хоосон байж болохгүй. This value should not be null. Энэ утга null байж болохгүй. This value should be null. Энэ утга null байна. This value is not valid. Энэ утга буруу байна. This value is not a valid time. Энэ утга буруу цаг төрөл байна. This value is not a valid URL. Энэ утга буруу URL байна . The two values should be equal. Хоёр утгууд ижил байх ёстой. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файл хэтэрхий том байна. Зөвшөөрөгдөх дээд хэмжээ нь {{ limit }} {{ suffix }} байна. The file is too large. Файл хэтэрхий том байна. The file could not be uploaded. Файл upload хийгдсэнгүй. This value should be a valid number. Энэ утга зөвхөн тоо байна. This value is not a valid country. Энэ утга үнэн бодит улс биш байна. This file is not a valid image. Файл зураг биш байна. This is not a valid IP address. IP хаяг зөв биш байна. This value is not a valid language. Энэ утга үнэн зөв хэл биш байна . PK]mwBB2Validator/Resources/translations/validators.pl.xlfnu[ This value should be false. Ta wartość powinna być fałszem. This value should be true. Ta wartość powinna być prawdą. This value should be of type {{ type }}. Ta wartość powinna być typu {{ type }}. This value should be blank. Ta wartość powinna być pusta. The value you selected is not a valid choice. Ta wartość powinna być jedną z podanych opcji. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Powinieneś wybrać co najmniej {{ limit }} opcję.|Powinieneś wybrać co najmniej {{ limit }} opcje.|Powinieneś wybrać co najmniej {{ limit }} opcji. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Powinieneś wybrać maksymalnie {{ limit }} opcję.|Powinieneś wybrać maksymalnie {{ limit }} opcje.|Powinieneś wybrać maksymalnie {{ limit }} opcji. One or more of the given values is invalid. Jedna lub więcej z podanych wartości jest nieprawidłowa. The fields {{ fields }} were not expected. Pola {{ fields }} nie były oczekiwane. The fields {{ fields }} are missing. Brakuje pól {{ fields }}. This value is not a valid date. Ta wartość nie jest prawidłową datą. This value is not a valid datetime. Ta wartość nie jest prawidłową datą i czasem. This value is not a valid email address. Ta wartość nie jest prawidłowym adresem email. The file could not be found. Plik nie mógł zostać odnaleziony. The file is not readable. Nie można odczytać pliku. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Plik jest za duży ({{ size }} {{ suffix }}). Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Nieprawidłowy typ mime pliku ({{ type }}). Dozwolone typy mime to {{ types }}. This value should be {{ limit }} or less. Ta wartość powinna wynosić {{ limit }} lub mniej. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków. This value should be {{ limit }} or more. Ta wartość powinna wynosić {{ limit }} lub więcej. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków. This value should not be blank. Ta wartość nie powinna być pusta. This value should not be null. Ta wartość nie powinna być nullem. This value should be null. Ta wartość powinna być nullem. This value is not valid. Ta wartość jest nieprawidłowa. This value is not a valid time. Ta wartość nie jest prawidłowym czasem. This value is not a valid URL. Ta wartość nie jest prawidłowym adresem URL. The two values should be equal. Obie wartości powinny być równe. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Plik jest za duży. Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}. The file is too large. Plik jest za duży. The file could not be uploaded. Plik nie mógł być wgrany. This value should be a valid number. Ta wartość powinna być prawidłową liczbą. This file is not a valid image. Ten plik nie jest obrazem. This is not a valid IP address. To nie jest prawidłowy adres IP. This value is not a valid language. Ta wartość nie jest prawidłowym językiem. This value is not a valid locale. Ta wartość nie jest prawidłową lokalizacją. This value is not a valid country. Ta wartość nie jest prawidłową nazwą kraju. This value is already used. Ta wartość jest już wykorzystywana. The size of the image could not be detected. Nie można wykryć rozmiaru obrazka. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Szerokość obrazka jest zbyt duża ({{ width }}px). Maksymalna dopuszczalna szerokość to {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Szerokość obrazka jest zbyt mała ({{ width }}px). Oczekiwana minimalna szerokość to {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Wysokość obrazka jest zbyt duża ({{ height }}px). Maksymalna dopuszczalna wysokość to {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Wysokość obrazka jest zbyt mała ({{ height }}px). Oczekiwana minimalna wysokość to {{ min_height }}px. This value should be the user current password. Ta wartość powinna być aktualnym hasłem użytkownika. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ta wartość powinna mieć dokładnie {{ limit }} znak.|Ta wartość powinna mieć dokładnie {{ limit }} znaki.|Ta wartość powinna mieć dokładnie {{ limit }} znaków. The file was only partially uploaded. Plik został wgrany tylko częściowo. No file was uploaded. Żaden plik nie został wgrany. No temporary folder was configured in php.ini. Nie skonfigurowano folderu tymczasowego w php.ini. Cannot write temporary file to disk. Nie można zapisać pliku tymczasowego na dysku. A PHP extension caused the upload to fail. Rozszerzenie PHP spowodowało błąd podczas wgrywania. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ten zbiór powinien zawierać {{ limit }} lub więcej elementów. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ten zbiór powinien zawierać {{ limit }} lub mniej elementów. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ten zbiór powinien zawierać dokładnie {{ limit }} element.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementy.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementów. Invalid card number. Nieprawidłowy numer karty. Unsupported card type or invalid card number. Nieobsługiwany rodzaj karty lub nieprawidłowy numer karty. This is not a valid International Bank Account Number (IBAN). Nieprawidłowy międzynarodowy numer rachunku bankowego (IBAN). This value is not a valid ISBN-10. Ta wartość nie jest prawidłowym numerem ISBN-10. This value is not a valid ISBN-13. Ta wartość nie jest prawidłowym numerem ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ta wartość nie jest prawidłowym numerem ISBN-10 ani ISBN-13. This value is not a valid ISSN. Ta wartość nie jest prawidłowym numerem ISSN. This value is not a valid currency. Ta wartość nie jest prawidłową walutą. This value should be equal to {{ compared_value }}. Ta wartość powinna być równa {{ compared_value }}. This value should be greater than {{ compared_value }}. Ta wartość powinna być większa niż {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ta wartość powinna być większa bądź równa {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ta wartość powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}. This value should be less than {{ compared_value }}. Ta wartość powinna być mniejsza niż {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ta wartość powinna być mniejsza bądź równa {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ta wartość nie powinna być równa {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ta wartość nie powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}. PK]nCC2Validator/Resources/translations/validators.sl.xlfnu[ This value should be false. Vrednost bi morala biti nepravilna (false). This value should be true. Vrednost bi morala biti pravilna (true). This value should be of type {{ type }}. Vrednost mora biti naslednjega tipa {{ type }}. This value should be blank. Vrednost mora biti prazna. The value you selected is not a valid choice. Vrednost, ki ste jo izbrali, ni veljavna možnost. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Izbrati morate vsaj {{ limit }} možnost.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Izberete lahko največ {{ limit }} možnost.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti. One or more of the given values is invalid. Ena ali več podanih vrednosti ni veljavnih. The fields {{ fields }} were not expected. Polja {{ fields }} niso bila pričakovana. The fields {{ fields }} are missing. Polja {{ fields }} manjkajo. This value is not a valid date. Ta vrednost ni veljaven datum. This value is not a valid datetime. Ta vrednost ni veljaven datum in čas. This value is not a valid email address. Ta vrednost ni veljaven e-poštni naslov. The file could not be found. Datoteke ni mogoče najti. The file is not readable. Datoteke ni mogoče prebrati. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika ({{ size }} {{ suffix }}). Največja dovoljena velikost je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime tip datoteke je neveljaven ({{ type }}). Dovoljeni mime tipi so {{ types }}. This value should be {{ limit }} or less. Ta vrednost bi morala biti {{ limit }} ali manj. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ta vrednost je predolga. Morala bi imeti {{ limit }} znak ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znaka ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znake ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znakov ali manj. This value should be {{ limit }} or more. Ta vrednost bi morala biti {{ limit }} ali več. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ta vrednost je prekratka. Morala bi imeti {{ limit }} znak ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znaka ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znake ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znakov ali več. This value should not be blank. Ta vrednost ne bi smela biti prazna. This value should not be null. Ta vrednost ne bi smela biti nedefinirana (null). This value should be null. Ta vrednost bi morala biti nedefinirana (null). This value is not valid. Ta vrednost ni veljavna. This value is not a valid time. Ta vrednost ni veljaven čas. This value is not a valid URL. Ta vrednost ni veljaven URL. The two values should be equal. Ti dve vrednosti bi morali biti enaki. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika. Največja dovoljena velikost je {{ limit }} {{ suffix }}. The file is too large. Datoteka je prevelika. The file could not be uploaded. Datoteke ni bilo mogoče naložiti. This value should be a valid number. Ta vrednost bi morala biti veljavna številka. This file is not a valid image. Ta datoteka ni veljavna slika. This is not a valid IP address. To ni veljaven IP naslov. This value is not a valid language. Ta vrednost ni veljaven jezik. This value is not a valid locale. Ta vrednost ni veljavna lokalnost. This value is not a valid country. Ta vrednost ni veljavna država. This value is already used. Ta vrednost je že uporabljena. The size of the image could not be detected. Velikosti slike ni bilo mogoče zaznati. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Širina slike je preširoka ({{ width }}px). Največja dovoljena širina je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Širina slike je premajhna ({{ width }}px). Najmanjša predvidena širina je {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Višina slike je prevelika ({{ height }}px). Največja dovoljena višina je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Višina slike je premajhna ({{ height }}px). Najmanjša predvidena višina je {{ min_height }}px. This value should be the user current password. Ta vrednost bi morala biti trenutno uporabnikovo geslo. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ta vrednost bi morala imeti točno {{ limit }} znak.|Ta vrednost bi morala imeti točno {{ limit }} znaka.|Ta vrednost bi morala imeti točno {{ limit }} znake.|Ta vrednost bi morala imeti točno {{ limit }} znakov. The file was only partially uploaded. Datoteka je bila le delno naložena. No file was uploaded. Nobena datoteka ni bila naložena. No temporary folder was configured in php.ini. Začasna mapa ni nastavljena v php.ini. Cannot write temporary file to disk. Začasne datoteke ni bilo mogoče zapisati na disk. A PHP extension caused the upload to fail. PHP razširitev je vzrok, da nalaganje ni uspelo. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ta zbirka bi morala vsebovati {{ limit }} element ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali več.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali več. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ta zbirka bi morala vsebovati {{ limit }} element ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali manj. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ta zbirka bi morala vsebovati točno {{ limit }} element.|Ta zbirka bi morala vsebovati točno {{ limit }} elementa.|Ta zbirka bi morala vsebovati točno {{ limit }} elemente.|Ta zbirka bi morala vsebovati točno {{ limit }} elementov. Invalid card number. Neveljavna številka kartice. Unsupported card type or invalid card number. Nepodprti tip kartice ali neveljavna številka kartice. This is not a valid International Bank Account Number (IBAN). To ni veljavna mednarodna številka bančnega računa (IBAN). This value is not a valid ISBN-10. Neveljavna vrednost po ISBN-10. This value is not a valid ISBN-13. Neveljavna vrednost po ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Neveljavna vrednost po ISBN-10 ali po ISBN-13. This value is not a valid ISSN. Neveljavna vrednost ISSN. This value is not a valid currency. Ta vrednost ni veljavna valuta. This value should be equal to {{ compared_value }}. Ta vrednost bi morala biti enaka {{ compared_value }}. This value should be greater than {{ compared_value }}. Ta vrednost bi morala biti večja od {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ta vrednost bi morala biti večja ali enaka {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ta vrednost bi morala biti identična {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ta vrednost bi morala biti manjša od {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ta vrednost bi morala biti manjša ali enaka {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ta vrednost ne bi smela biti enaka {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ta vrednost ne bi smela biti identična {{ compared_value_type }} {{ compared_value }}. PK]MM2Validator/Resources/translations/validators.el.xlfnu[ This value should be false. Αυτή η τιμή πρέπει να είναι ψευδής. This value should be true. Αυτή η τιμή πρέπει να είναι αληθής. This value should be of type {{ type }}. Αυτή η τιμή πρέπει να είναι τύπου {{ type }}. This value should be blank. Αυτή η τιμή πρέπει να είναι κενή. The value you selected is not a valid choice. Η τιμή που επιλέχθηκε δεν αντιστοιχεί σε έγκυρη επιλογή. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογή.|Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογές. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογή.|Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογές. One or more of the given values is invalid. Μια ή περισσότερες τιμές δεν είναι έγκυρες. The fields {{ fields }} were not expected. Τα πεδία {{ fields }} δεν ήταν αναμενόμενα. The fields {{ fields }} are missing. Τα πεδία {{ fields }} απουσιάζουν. This value is not a valid date. Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία. This value is not a valid datetime. Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία και ώρα. This value is not a valid email address. Η τιμή δεν αντιστοιχεί σε έγκυρο email. The file could not be found. Το αρχείο δε μπορεί να βρεθεί. The file is not readable. Το αρχείο δεν είναι αναγνώσιμο. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Το αρχείο είναι πολύ μεγάλο ({{ size }} {{ suffix }}). Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Ο τύπος mime του αρχείου δεν είναι έγκυρος ({{ type }}). Οι έγκρυοι τύποι mime είναι {{ types }}. This value should be {{ limit }} or less. Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή λιγότερο. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή λιγότερο.|Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή λιγότερο. This value should be {{ limit }} or more. Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή περισσότερο. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή περισσότερο.|Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή περισσότερο. This value should not be blank. Αυτή η τιμή δεν πρέπει να είναι κενή. This value should not be null. Αυτή η τιμή δεν πρέπει να είναι μηδενική. This value should be null. Αυτή η τιμή πρέπει να είναι μηδενική. This value is not valid. Αυτή η τιμή δεν είναι έκγυρη. This value is not a valid time. Αυτή η τιμή δεν αντιστοιχεί σε έγκυρη ώρα. This value is not a valid URL. Αυτή η τιμή δεν αντιστοιχεί σε έγκυρο URL. The two values should be equal. Οι δύο τιμές θα πρέπει να είναι ίδιες. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Το αρχείο είναι πολύ μεγάλο. Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}. The file is too large. Το αρχείο είναι πολύ μεγάλο. The file could not be uploaded. Το αρχείο δε μπορεί να ανέβει. This value should be a valid number. Αυτή η τιμή θα πρέπει να είναι ένας έγκυρος αριθμός. This file is not a valid image. Το αρχείο δεν αποτελεί έγκυρη εικόνα. This is not a valid IP address. Αυτό δεν είναι μια έκγυρη διεύθυνση IP. This value is not a valid language. Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη γλώσσα. This value is not a valid locale. Αυτή η τιμή δεν αντιστοιχεί σε έκγυρο κωδικό τοποθεσίας. This value is not a valid country. Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη χώρα. This value is already used. Αυτή η τιμή χρησιμοποιείται ήδη. The size of the image could not be detected. Το μέγεθος της εικόνας δεν ήταν δυνατό να ανιχνευθεί. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Το πλάτος της εικόνας είναι πολύ μεγάλο ({{ width }}px). Το μέγιστο επιτρεπτό πλάτος είναι {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Το πλάτος της εικόνας είναι πολύ μικρό ({{ width }}px). Το ελάχιστο επιτρεπτό πλάτος είναι {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Το ύψος της εικόνας είναι πολύ μεγάλο ({{ height }}px). Το μέγιστο επιτρεπτό ύψος είναι {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Το ύψος της εικόνας είναι πολύ μικρό ({{ height }}px). Το ελάχιστο επιτρεπτό ύψος είναι {{ min_height }}px. This value should be the user current password. Αυτή η τιμή θα έπρεπε να είναι ο τρέχων κωδικός. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρα.|Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρες. The file was only partially uploaded. Το αρχείο δεν ανέβηκε ολόκληρο. No file was uploaded. Δεν ανέβηκε κανένα αρχείο. No temporary folder was configured in php.ini. Κανένας προσωρινός φάκελος δεν έχει ρυθμιστεί στο php.ini. Cannot write temporary file to disk. Αδυναμία εγγραφής προσωρινού αρχείου στο δίσκο. A PHP extension caused the upload to fail. Μια επέκταση PHP προκάλεσε αδυναμία ανεβάσματος. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείο ή περισσότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή περισσότερα. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείo ή λιγότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή λιγότερα. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχείo.|Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχεία. Invalid card number. Μη έγκυρος αριθμός κάρτας. Unsupported card type or invalid card number. Μη υποστηριζόμενος τύπος κάρτας ή μη έγκυρος αριθμός κάρτας. This is not a valid International Bank Account Number (IBAN). Αυτό δεν αντιστοιχεί σε έκγυρο διεθνή αριθμό τραπεζικού λογαριασμού (IBAN). This value is not a valid ISBN-10. Αυτό δεν είναι έγκυρος κωδικός ISBN-10. This value is not a valid ISBN-13. Αυτό δεν είναι έγκυρος κωδικός ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Αυτό δεν είναι ούτε έγκυρος κωδικός ISBN-10 ούτε έγκυρος κωδικός ISBN-13. This value is not a valid ISSN. Αυτό δεν είναι έγκυρος κωδικός ISSN. This value is not a valid currency. Αυτό δεν αντιστοιχεί σε έγκυρο νόμισμα. This value should be equal to {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι ίση με {{ compared_value }}. This value should be greater than {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη από {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη ή ίση με {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μικρότερη από {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μικρότερη ή ίση με {{ compared_value }}. This value should not be equal to {{ compared_value }}. Αυτή η τιμή δεν θα πρέπει να είναι ίση με {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Αυτή η τιμή δεν πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}. PK]Y.3552Validator/Resources/translations/validators.sq.xlfnu[ This value should be false. Kjo vlerë duhet të jetë e pavërtetë (false). This value should be true. Kjo vlerë duhet të jetë e vërtetë (true). This value should be of type {{ type }}. Kjo vlerë duhet të jetë e llojit {{ type }}. This value should be blank. Kjo vlerë duhet të jetë e zbrazët. The value you selected is not a valid choice. Vlera që keni zgjedhur nuk është alternativë e vlefshme. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Duhet të zgjedhni së paku {{ limit }} alternativa.|Duhet të zgjedhni së paku {{ limit }} alternativa. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Duhet të zgjedhni më së shumti {{ limit }} alternativa.|Duhet të zgjedhni më së shumti {{ limit }} alternativa. One or more of the given values is invalid. Një apo më shumë nga vlerat e dhëna nuk janë të sakta. The fields {{ fields }} were not expected. Fushat {{ fields }} nuk ishin të pritura. The fields {{ fields }} are missing. Fushat {{ fields }} mungojnë. This value is not a valid date. Kjo vlerë nuk është datë e vlefshme. This value is not a valid datetime. Kjo vlerë nuk është datë-kohë e vlefshme. This value is not a valid email address. Kjo vlerë nuk është e-mail adresë e vlefshme. The file could not be found. File nuk mund të gjindej. The file is not readable. File nuk është i lexueshëm. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. File është shumë i madh ({{ size }} {{ suffix }}). Madhësia më e madhe e lejuar është {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Lloji mime i files nuk është i vlefshëm ({{ type }}). Llojet mime të lejuara janë {{ types }}. This value should be {{ limit }} or less. Kjo vlerë duhet të jetë {{ limit }} ose më pak. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere.|Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere. This value should be {{ limit }} or more. Kjo vlerë duhet të jetë {{ limit }} ose më shumë. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere.|Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere. This value should not be blank. Kjo vlerë nuk duhet të jetë e zbrazët. This value should not be null. Kjo vlerë nuk duhet të jetë null. This value should be null. Kjo vlerë duhet të jetë null. This value is not valid. Kjo vlerë nuk është e vlefshme. This value is not a valid time. Kjo vlerë nuk është kohë e vlefshme. This value is not a valid URL. Kjo vlerë nuk është URL e vlefshme. The two values should be equal. Këto dy vlera duhet të jenë të barabarta. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ky file është shumë i madh. Madhësia maksimale e lejuar është {{ limit }} {{ suffix }}. The file is too large. Ky file është shumë i madh. The file could not be uploaded. Ky file nuk mund të ngarkohet. This value should be a valid number. Kjo vlerë duhet të jetë numër i vlefshëm. This file is not a valid image. Ky file nuk është imazh i vlefshëm. This is not a valid IP address. Kjo vlerë nuk është IP adresë e vlefshme. This value is not a valid language. Kjo vlerë nuk është gjuhë e vlefshme. This value is not a valid locale. Kjo vlerë nuk është përcaktim rajonal i vlefshëm. This value is not a valid country. Kjo vlerë nuk është shtet i vlefshëm. This value is already used. Kjo vlerë është tashmë në përdorim. The size of the image could not be detected. Madhësia e këtij imazhi nuk mund të zbulohet. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Gjerësia e imazhit është shumë e madhe ({{ width }}px). Gjerësia maksimale e lejuar është {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Gjerësia e imazhit është shumë e vogël ({{ width }}px). Gjerësia minimale e pritur është {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Gjatësia e imazhit është shumë e madhe ({{ height }}px). Gjatësia maksimale e lejuar është {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Gjatësia e imazhit është shumë e vogël ({{ height }}px). Gjatësia minimale e pritur është {{ min_height }}px. This value should be the user current password. Kjo vlerë duhet të jetë fjalëkalimi aktual i përdoruesit. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere.|Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere. The file was only partially uploaded. Ky file është ngarkuar pjesërisht. No file was uploaded. Nuk është ngarkuar ndonjë file. No temporary folder was configured in php.ini. Asnjë folder i përkohshëm nuk është konfiguruar në php.ini. Cannot write temporary file to disk. Nuk mund të shkruhet file i përkohshëm në disk. A PHP extension caused the upload to fail. Një ekstenzion i PHP-së bëri të dështojë ngarkimi i files. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente.|Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente. Invalid card number. Numër kartele i pavlefshëm. Unsupported card type or invalid card number. Lloj kartele i pambështetur ose numër kartele i pavlefshëm. PK]9>552Validator/Resources/translations/validators.da.xlfnu[ This value should be false. Værdien skal være falsk. This value should be true. Værdien skal være sand. This value should be of type {{ type }}. Værdien skal være af typen {{ type }}. This value should be blank. Værdien skal være blank. The value you selected is not a valid choice. Værdien skal være en af de givne muligheder. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du skal vælge mindst {{ limit }} muligheder. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan højest vælge {{ limit }} muligheder. One or more of the given values is invalid. En eller flere af de oplyste værdier er ugyldige. The fields {{ fields }} were not expected. Felterne {{ fields }} var ikke forventet. The fields {{ fields }} are missing. Felterne {{ fields }} mangler. This value is not a valid date. Værdien er ikke en gyldig dato. This value is not a valid datetime. Værdien er ikke en gyldig dato og tid. This value is not a valid email address. Værdien er ikke en gyldig e-mail adresse. The file could not be found. Filen kunne ikke findes. The file is not readable. Filen kan ikke læses. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor ({{ size }} {{ suffix }}). Tilladte maksimale størrelse {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mimetypen af filen er ugyldig ({{ type }}). Tilladte mimetyper er {{ types }}. This value should be {{ limit }} or less. Værdien skal være {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Værdien er for lang. Den skal have {{ limit }} bogstaver eller mindre. This value should be {{ limit }} or more. Værdien skal være {{ limit }} eller mere. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Værdien er for kort. Den skal have {{ limit }} tegn eller flere. This value should not be blank. Værdien må ikke være blank. This value should not be null. Værdien må ikke være tom (null). This value should be null. Værdien skal være tom (null). This value is not valid. Værdien er ikke gyldig. This value is not a valid time. Værdien er ikke en gyldig tid. This value is not a valid URL. Værdien er ikke en gyldig URL. The two values should be equal. De to værdier skal være ens. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}. The file is too large. Filen er for stor. The file could not be uploaded. Filen kunne ikke blive uploadet. This value should be a valid number. Værdien skal være et gyldigt tal. This file is not a valid image. Filen er ikke gyldigt billede. This is not a valid IP address. Dette er ikke en gyldig IP adresse. This value is not a valid language. Værdien er ikke et gyldigt sprog. This value is not a valid locale. Værdien er ikke en gyldig lokalitet. This value is not a valid country. Værdien er ikke et gyldigt land. This value is already used. Værdien er allerede i brug. The size of the image could not be detected. Størrelsen på billedet kunne ikke detekteres. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Billedbredden er for stor ({{ width }}px). Tilladt maksimumsbredde er {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Billedebredden er for lille ({{ width }}px). Forventet minimumshøjde er {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Billedhøjden er for stor ({{ height }}px). Tilladt maksimumshøjde er {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Billedhøjden er for lille ({{ height }}px). Forventet minimumshøjde er {{ min_height }}px. This value should be the user current password. Værdien skal være brugerens nuværende password. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Værdien skal have præcis {{ limit }} tegn. The file was only partially uploaded. Filen var kun delvis uploadet. No file was uploaded. Ingen fil blev uploadet. No temporary folder was configured in php.ini. Ingen midlertidig mappe er konfigureret i php.ini. Cannot write temporary file to disk. Kan ikke skrive midlertidig fil til disk. A PHP extension caused the upload to fail. En PHP udvidelse forårsagede fejl i upload. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Denne samling skal indeholde {{ limit }} element eller flere.|Denne samling skal indeholde {{ limit }} elementer eller flere. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Denne samling skal indeholde {{ limit }} element eller mindre.|Denne samling skal indeholde {{ limit }} elementer eller mindre. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Denne samling skal indeholde præcis {{ limit }} element.|Denne samling skal indeholde præcis {{ limit }} elementer. Invalid card number. Ugyldigt kortnummer. Unsupported card type or invalid card number. Ikke-understøttet korttype eller ugyldigt kortnummer. This is not a valid International Bank Account Number (IBAN). Det er ikke en gyldig International Bank Account Number (IBAN). This value is not a valid ISBN-10. Værdien er ikke en gyldig ISBN-10. This value is not a valid ISBN-13. Værdien er ikke en gyldig ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Værdien er hverken en gyldig ISBN-10 eller en gyldig ISBN-13. This value is not a valid ISSN. Værdien er ikke en gyldig ISSN. PK]a222Validator/Resources/translations/validators.fi.xlfnu[ This value should be false. Arvon tulee olla epätosi. This value should be true. Arvon tulee olla tosi. This value should be of type {{ type }}. Arvon tulee olla tyyppiä {{ type }}. This value should be blank. Arvon tulee olla tyhjä. The value you selected is not a valid choice. Arvon tulee olla yksi annetuista vaihtoehdoista. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Sinun tulee valita vähintään {{ limit }} vaihtoehtoa. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Sinun tulee valitan enintään {{ limit }} vaihtoehtoa. One or more of the given values is invalid. Yksi tai useampi annetuista arvoista on virheellinen. The fields {{ fields }} were not expected. Odottamattomia kenttiä {{ fields }}. The fields {{ fields }} are missing. Kentät {{ fields }} puuttuvat. This value is not a valid date. Annettu arvo ei ole kelvollinen päivämäärä. This value is not a valid datetime. Annettu arvo ei ole kelvollinen päivämäärä ja kellonaika. This value is not a valid email address. Annettu arvo ei ole kelvollinen sähköpostiosoite. The file could not be found. Tiedostoa ei löydy. The file is not readable. Tiedostoa ei voida lukea. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Tiedostonkoko ({{ size }} {{ suffix }}) on liian iso. Suurin sallittu tiedostonkoko on {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Tiedostotyyppi ({{ type }}) on virheellinen. Sallittuja tiedostotyyppejä ovat {{ types }}. This value should be {{ limit }} or less. Arvon tulee olla {{ limit }} tai vähemmän. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Liian pitkä syöte. Syöte saa olla enintään {{ limit }} merkkiä. This value should be {{ limit }} or more. Arvon tulee olla {{ limit }} tai enemmän. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Liian lyhyt syöte. Syötteen tulee olla vähintään {{ limit }} merkkiä. This value should not be blank. Kenttä ei voi olla tyhjä. This value should not be null. Syöte ei voi olla null. This value should be null. Syötteen tulee olla null. This value is not valid. Virheellinen arvo. This value is not a valid time. Annettu arvo ei ole kelvollinen kellonaika. This value is not a valid URL. Annettu arvo ei ole kelvollinen URL-osoite. The two values should be equal. Kahden annetun arvon tulee olla samat. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Annettu tiedosto on liian iso. Suurin sallittu tiedostokoko on {{ limit }} {{ suffix }}. The file is too large. Tiedosto on liian iso. The file could not be uploaded. Tiedoston siirto epäonnistui. This value should be a valid number. Tämän arvon tulee olla numero. This file is not a valid image. Tämä tiedosto ei ole kelvollinen kuva. This is not a valid IP address. Tämä ei ole kelvollinen IP-osoite. This value is not a valid language. Tämä arvo ei ole kelvollinen kieli. This value is not a valid locale. Tämä arvo ei ole kelvollinen kieli- ja alueasetus (locale). This value is not a valid country. Tämä arvo ei ole kelvollinen maa. This value is already used. Tämä arvo on jo käytetty. The size of the image could not be detected. Kuvan kokoa ei voitu tunnistaa. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Kuva on liian leveä ({{ width }}px). Sallittu maksimileveys on {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Kuva on liian kapea ({{ width }}px). Leveyden tulisi olla vähintään {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Kuva on liian korkea ({{ width }}px). Sallittu maksimikorkeus on {{ max_width }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Kuva on liian matala ({{ height }}px). Korkeuden tulisi olla vähintään {{ min_height }}px. This value should be the user current password. Tämän arvon tulisi olla käyttäjän tämänhetkinen salasana. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Tämän arvon tulisi olla tasan yhden merkin pituinen.|Tämän arvon tulisi olla tasan {{ limit }} merkkiä pitkä. The file was only partially uploaded. Tiedosto ladattiin vain osittain. No file was uploaded. Tiedostoa ei ladattu. No temporary folder was configured in php.ini. Väliaikaishakemistoa ei ole asetettu php.ini -tiedostoon. Cannot write temporary file to disk. Väliaikaistiedostoa ei voitu kirjoittaa levylle. A PHP extension caused the upload to fail. PHP-laajennoksen vuoksi tiedoston lataus epäonnistui. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Tässä ryhmässä tulisi olla yksi tai useampi elementti.|Tässä ryhmässä tulisi olla vähintään {{ limit }} elementtiä. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Tässä ryhmässä tulisi olla enintään yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Tässä ryhmässä tulisi olla tasan yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä. Invalid card number. Virheellinen korttinumero. Unsupported card type or invalid card number. Tätä korttityyppiä ei tueta tai korttinumero on virheellinen. PK]Tл@@5Validator/Resources/translations/validators.pt_BR.xlfnu[ This value should be false. Este valor deve ser falso. This value should be true. Este valor deve ser verdadeiro. This value should be of type {{ type }}. Este valor deve ser do tipo {{ type }}. This value should be blank. Este valor deve ser vazio. The value you selected is not a valid choice. O valor selecionado não é uma opção válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Você deve selecionar, no mínimo, {{ limit }} opção.|Você deve selecionar, no mínimo, {{ limit }} opções. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Você deve selecionar, no máximo, {{ limit }} opção.|Você deve selecionar, no máximo, {{ limit }} opções. One or more of the given values is invalid. Um ou mais valores informados são inválidos. The fields {{ fields }} were not expected. Os campos {{ fields }} não são esperados. The fields {{ fields }} are missing. Os campos {{ fields }} estão ausentes. This value is not a valid date. Este valor não é uma data válida. This value is not a valid datetime. Este valor não é uma data e hora válida. This value is not a valid email address. Este valor não é um endereço de e-mail válido. The file could not be found. O arquivo não foi encontrado. The file is not readable. O arquivo não pode ser lido. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}. This value should be {{ limit }} or less. Este valor deve ser {{ limit }} ou menos. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Este valor é muito longo. Deve ter {{ limit }} caractere ou menos.|Este valor é muito longo. Deve ter {{ limit }} caracteres ou menos. This value should be {{ limit }} or more. Este valor deve ser {{ limit }} ou mais. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Este valor é muito curto. Deve ter {{ limit }} caractere ou mais.|Este valor é muito curto. Deve ter {{ limit }} caracteres ou mais. This value should not be blank. Este valor não deve ser vazio. This value should not be null. Este valor não deve ser nulo. This value should be null. Este valor deve ser nulo. This value is not valid. Este valor não é válido. This value is not a valid time. Este valor não é uma hora válida. This value is not a valid URL. Este valor não é uma URL válida. The two values should be equal. Os dois valores devem ser iguais. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}. The file is too large. O arquivo é muito grande. The file could not be uploaded. O arquivo não pode ser enviado. This value should be a valid number. Este valor deve ser um número válido. This file is not a valid image. Este arquivo não é uma imagem válida. This is not a valid IP address. Este não é um endereço de IP válido. This value is not a valid language. Este valor não é um idioma válido. This value is not a valid locale. Este valor não é uma localidade válida. This value is not a valid country. Este valor não é um país válido. This value is already used. Este valor já está sendo usado. The size of the image could not be detected. O tamanho da imagem não pode ser detectado. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A largura da imagem é muito grande ({{ width }}px). A largura máxima permitida é de {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A largura da imagem é muito pequena ({{ width }}px). A largura mínima esperada é de {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A altura da imagem é muito grande ({{ height }}px). A altura máxima permitida é de {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A altura da imagem é muito pequena ({{ height }}px). A altura mínima esperada é de {{ min_height }}px. This value should be the user current password. Este valor deve ser a senha atual do usuário. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor deve ter exatamente {{ limit }} caractere.|Este valor deve ter exatamente {{ limit }} caracteres. The file was only partially uploaded. O arquivo foi enviado apenas parcialmente. No file was uploaded. Nenhum arquivo foi enviado. No temporary folder was configured in php.ini. Nenhum diretório temporário foi configurado no php.ini. Cannot write temporary file to disk. Não foi possível escrever o arquivo temporário no disco. A PHP extension caused the upload to fail. Uma extensão PHP fez com que o envio falhasse. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos. Invalid card number. Número de cartão inválido. Unsupported card type or invalid card number. Tipo de cartão não suportado ou número de cartão inválido. This is not a valid International Bank Account Number (IBAN). Este não é um Número Internacional de Conta Bancária (IBAN) válido. This value is not a valid ISBN-10. Este valor não é um ISBN-10 válido. This value is not a valid ISBN-13. Este valor não é um ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor não é um ISBN-10 e nem um ISBN-13 válido. This value is not a valid ISSN. Este valor não é um ISSN válido. This value is not a valid currency. Este não é um valor monetário válido. This value should be equal to {{ compared_value }}. Este valor deve ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor deve ser maior que {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor deve ser maior ou igual a {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor deve ser menor que {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor deve ser menor ou igual a {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor não deve ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor não deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. PK]PhBhB2Validator/Resources/translations/validators.lt.xlfnu[ This value should be false. Reikšmė turi būti neigiama. This value should be true. Reikšmė turi būti teigiama. This value should be of type {{ type }}. Šios reikšmės tipas turi būti {{ type }}. This value should be blank. Ši reikšmė turi būti tuščia. The value you selected is not a valid choice. Neteisingas pasirinkimas. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Turite pasirinkti bent {{ limit }} variantą.|Turite pasirinkti bent {{ limit }} variantus.|Turite pasirinkti bent {{ limit }} variantų. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Turite pasirinkti ne daugiau kaip {{ limit }} variantą.|Turite pasirinkti ne daugiau kaip {{ limit }} variantus.|Turite pasirinkti ne daugiau kaip {{ limit }} variantų. One or more of the given values is invalid. Viena ar daugiau įvestų reikšmių yra netinkamos. The fields {{ fields }} were not expected. Laukai {{ fields }} yra nenumatyti. The fields {{ fields }} are missing. Trūkstami laukai {{ fields }}. This value is not a valid date. Ši reikšmė nėra data. This value is not a valid datetime. Ši reikšmė nera data ir laikas. This value is not a valid email address. Ši reikšmė nėra tinkamas el. pašto adresas. The file could not be found. Byla nerasta. The file is not readable. Negalima nuskaityti bylos. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Byla yra per didelė ({{ size }} {{ suffix }}). Maksimalus dydis {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Netinkamas bylos tipas (mime type) ({{ type }}). Galimi bylų tipai {{ types }}. This value should be {{ limit }} or less. Reikšmė turi būti {{ limit }} arba mažiau. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių. This value should be {{ limit }} or more. Reikšmė turi būti {{ limit }} arba daugiau. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių. This value should not be blank. Ši reikšmė negali būti tuščia. This value should not be null. Ši reikšmė negali būti null. This value should be null. Ši reikšmė turi būti null. This value is not valid. Netinkama reikšmė. This value is not a valid time. Ši reikšmė nėra laikas. This value is not a valid URL. Ši reikšmė nėra tinkamas interneto adresas. The two values should be equal. Abi reikšmės turi būti identiškos. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Byla yra per didelė. Maksimalus dydis yra {{ limit }} {{ suffix }}. The file is too large. Byla per didelė. The file could not be uploaded. Byla negali būti įkelta. This value should be a valid number. Ši reikšmė turi būti skaičius. This value is not a valid country. Ši reikšmė nėra tinkama šalis. This file is not a valid image. Byla nėra paveikslėlis. This is not a valid IP address. Ši reikšmė nėra tinkamas IP adresas. This value is not a valid language. Ši reikšmė nėra tinkama kalba. This value is not a valid locale. Ši reikšmė nėra tinkama lokalė. This value is already used. Ši reikšmė jau yra naudojama. The size of the image could not be detected. Nepavyko nustatyti nuotraukos dydžio. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Nuotraukos plotis per didelis ({{ width }}px). Maksimalus leidžiamas plotis yra {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Nuotraukos plotis per mažas ({{ width }}px). Minimalus leidžiamas plotis yra {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Nuotraukos aukštis per didelis ({{ height }}px). Maksimalus leidžiamas aukštis yra {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Nuotraukos aukštis per mažas ({{ height }}px). Minimalus leidžiamas aukštis yra {{ min_height }}px. This value should be the user current password. Ši reikšmė turi sutapti su dabartiniu naudotojo slaptažodžiu. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ši reikšmė turi turėti lygiai {{ limit }} simbolį.|Ši reikšmė turi turėti lygiai {{ limit }} simbolius.|Ši reikšmė turi turėti lygiai {{ limit }} simbolių. The file was only partially uploaded. Failas buvo tik dalinai įkeltas. No file was uploaded. Nebuvo įkelta jokių failų. No temporary folder was configured in php.ini. Nėra sukonfiguruoto jokio laikino katalogo php.ini faile. Cannot write temporary file to disk. Nepavyko išsaugoti laikino failo. A PHP extension caused the upload to fail. PHP plėtinys sutrukdė failo įkėlimą ir jis nepavyko. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Sąraše turi būti lygiai {{ limit }} įrašas.|Sąraše turi būti lygiai {{ limit }} įrašai.|Sąraše turi būti lygiai {{ limit }} įrašų. Invalid card number. Klaidingas kortelės numeris. Unsupported card type or invalid card number. Kortelės tipas nepalaikomas arba klaidingas kortelės numeris. This is not a valid International Bank Account Number (IBAN). Ši reišmė neatitinka tarptautinio banko sąskaitos numerio formato (IBAN). This value is not a valid ISBN-10. Ši reikšmė neatitinka ISBN-10 formato. This value is not a valid ISBN-13. Ši reikšmė neatitinka ISBN-13 formato. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ši reikšmė neatitinka nei ISBN-10, nei ISBN-13 formato. This value is not a valid ISSN. Ši reišmė neatitinka ISSN formato. This value is not a valid currency. Netinkamas valiutos formatas. This value should be equal to {{ compared_value }}. Ši reikšmė turi būti lygi {{ compared_value }}. This value should be greater than {{ compared_value }}. Ši reikšmė turi būti didesnė už {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ši reikšmė turi būti didesnė už arba lygi {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ši reikšmė turi būti identiška {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ši reikšmė turi būti mažesnė už {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ši reikšmė turi būti mažesnė už arba lygi {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ši reikšmė neturi būti lygi {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ši reikšmė neturi būti identiška {{ compared_value_type }} {{ compared_value }}. PK]ժN@@2Validator/Resources/translations/validators.nl.xlfnu[ This value should be false. Deze waarde mag niet waar zijn. This value should be true. Deze waarde moet waar zijn. This value should be of type {{ type }}. Deze waarde moet van het type {{ type }} zijn. This value should be blank. Deze waarde moet leeg zijn. The value you selected is not a valid choice. De geselecteerde waarde is geen geldige optie. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Selecteer ten minste {{ limit }} optie.|Selecteer ten minste {{ limit }} opties. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Selecteer maximaal {{ limit }} optie.|Selecteer maximaal {{ limit }} opties. One or more of the given values is invalid. Eén of meer van de ingegeven waarden zijn ongeldig. The fields {{ fields }} were not expected. De velden {{ fields }} werden niet verwacht. The fields {{ fields }} are missing. De velden {{ fields }} ontbreken. This value is not a valid date. Deze waarde is geen geldige datum. This value is not a valid datetime. Deze waarde is geen geldige datum en tijd. This value is not a valid email address. Deze waarde is geen geldig e-mailadres. The file could not be found. Het bestand is niet gevonden. The file is not readable. Het bestand is niet leesbaar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Het bestand is te groot ({{ size }} {{ suffix }}). Toegestane maximum grootte is {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Het mime type van het bestand is ongeldig ({{ type }}). Toegestane mime types zijn {{ types }}. This value should be {{ limit }} or less. Deze waarde moet {{ limit }} of minder zijn. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Deze waarde is te lang. Hij mag maximaal {{ limit }} teken bevatten.|Deze waarde is te lang. Hij mag maximaal {{ limit }} tekens bevatten. This value should be {{ limit }} or more. Deze waarde moet {{ limit }} of meer zijn. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Deze waarde is te kort. Hij moet tenminste {{ limit }} teken bevatten.|Deze waarde is te kort. Hij moet tenminste {{ limit }} tekens bevatten. This value should not be blank. Deze waarde mag niet leeg zijn. This value should not be null. Deze waarde mag niet null zijn. This value should be null. Deze waarde moet null zijn. This value is not valid. Deze waarde is ongeldig. This value is not a valid time. Deze waarde is geen geldige tijd. This value is not a valid URL. Deze waarde is geen geldige URL. The two values should be equal. De twee waarden moeten gelijk zijn. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Het bestand is te groot. Toegestane maximum grootte is {{ limit }} {{ suffix }}. The file is too large. Het bestand is te groot. The file could not be uploaded. Het bestand kon niet geüpload worden. This value should be a valid number. Deze waarde moet een geldig getal zijn. This file is not a valid image. Dit bestand is geen geldige afbeelding. This is not a valid IP address. Dit is geen geldig IP-adres. This value is not a valid language. Deze waarde representeert geen geldige taal. This value is not a valid locale. Deze waarde representeert geen geldige lokalisering. This value is not a valid country. Deze waarde representeert geen geldig land. This value is already used. Deze waarde wordt al gebruikt. The size of the image could not be detected. De grootte van de afbeelding kon niet bepaald worden. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. De afbeelding is te breed ({{ width }}px). De maximaal toegestane breedte is {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. De afbeelding is niet breed genoeg ({{ width }}px). De minimaal verwachte breedte is {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. De afbeelding is te hoog ({{ height }}px). De maximaal toegestane hoogte is {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. De afbeelding is niet hoog genoeg ({{ height }}px). De minimaal verwachte hoogte is {{ min_height }}px. This value should be the user current password. Deze waarde moet het huidige wachtwoord van de gebruiker zijn. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Deze waarde moet exact {{ limit }} tekens lang zijn. The file was only partially uploaded. Het bestand is niet geheel geüpload. No file was uploaded. Er is geen bestand geüpload. No temporary folder was configured in php.ini. Er is geen tijdelijke map geconfigureerd in php.ini. Cannot write temporary file to disk. Kan het tijdelijke bestand niet wegschrijven op disk. A PHP extension caused the upload to fail. De upload is mislukt vanwege een PHP-extensie. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Deze collectie moet {{ limit }} element of meer bevatten.|Deze collectie moet {{ limit }} elementen of meer bevatten. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Deze collectie moet {{ limit }} element of minder bevatten.|Deze collectie moet {{ limit }} elementen of minder bevatten. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Deze collectie moet exact {{ limit }} element bevatten.|Deze collectie moet exact {{ limit }} elementen bevatten. Invalid card number. Ongeldig creditcardnummer. Unsupported card type or invalid card number. Niet-ondersteund type creditcard of ongeldig nummer. This is not a valid International Bank Account Number (IBAN). Dit is geen geldig internationaal bankrekeningnummer (IBAN). This value is not a valid ISBN-10. Deze waarde is geen geldige ISBN-10. This value is not a valid ISBN-13. Deze waarde is geen geldige ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Deze waarde is geen geldige ISBN-10 of ISBN-13 waarde. This value is not a valid ISSN. Deze waarde is geen geldige ISSN waarde. This value is not a valid currency. Deze waarde is geen geldige valuta. This value should be equal to {{ compared_value }}. Deze waarde moet gelijk zijn aan {{ compared_value }}. This value should be greater than {{ compared_value }}. Deze waarde moet groter zijn dan {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Deze waarde moet groter dan of gelijk aan {{ compared_value }} zijn. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Deze waarde moet identiek zijn aan {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Deze waarde moet minder zijn dan {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Deze waarde moet minder dan of gelijk aan {{ compared_value }} zijn. This value should not be equal to {{ compared_value }}. Deze waarde mag niet gelijk zijn aan {{ compared_value }}. This value should not be identical to {{ compared_value }}. Deze waarde mag niet identiek zijn aan {{ compared_value }}. PK]Q>??2Validator/Resources/translations/validators.sv.xlfnu[ This value should be false. Värdet ska vara falskt. This value should be true. Värdet ska vara sant. This value should be of type {{ type }}. Värdet ska vara av typen {{ type }}. This value should be blank. Värdet ska vara tomt. The value you selected is not a valid choice. Värdet ska vara ett av de givna valen. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du måste välja minst {{ limit }} val.|Du måste välja minst {{ limit }} val. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan som mest välja {{ limit }} val.|Du kan som mest välja {{ limit }} val. One or more of the given values is invalid. Ett eller fler av de angivna värdena är ogiltigt. The fields {{ fields }} were not expected. Fälten {{ fields }} var oväntade. The fields {{ fields }} are missing. Fälten {{ fields }} saknas. This value is not a valid date. Värdet är inte ett giltigt datum. This value is not a valid datetime. Värdet är inte ett giltigt datum med tid. This value is not a valid email address. Värdet är inte en giltig epost-adress. The file could not be found. Filen kunde inte hittas. The file is not readable. Filen är inte läsbar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Filen är för stor ({{ size }} {{ suffix }}). Största tillåtna storlek är {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Filens MIME-typ ({{ type }}) är ogiltig. De tillåtna typerna är {{ types }}. This value should be {{ limit }} or less. Värdet ska vara {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Värdet är för långt. Det ska ha {{ limit }} tecken eller färre.|Värdet är för långt. Det ska ha {{ limit }} tecken eller färre. This value should be {{ limit }} or more. Värdet ska vara {{ limit }} eller mer. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Värdet är för kort. Det ska ha {{ limit }} tecken eller mer.|Värdet är för kort. Det ska ha {{ limit }} tecken eller mer. This value should not be blank. Värdet kan inte vara tomt. This value should not be null. Värdet kan inte vara null. This value should be null. Värdet ska vara null. This value is not valid. Värdet är inte giltigt. This value is not a valid time. Värdet är inte en giltig tid. This value is not a valid URL. Värdet är inte en giltig URL. The two values should be equal. De två värdena måste vara lika. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Filen är för stor. Tillåten maximal storlek är {{ limit }} {{ suffix }}. The file is too large. Filen är för stor. The file could not be uploaded. Filen kunde inte laddas upp. This value should be a valid number. Värdet ska vara ett giltigt nummer. This file is not a valid image. Filen är ingen giltig bild. This is not a valid IP address. Det här är inte en giltig IP-adress. This value is not a valid language. Värdet är inte ett giltigt språk. This value is not a valid locale. Värdet är inte en giltig plats. This value is not a valid country. Värdet är inte ett giltigt land. This value is already used. Värdet används redan. The size of the image could not be detected. Det gick inte att fastställa storleken på bilden. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Bildens bredd är för stor ({{ width }}px). Tillåten maximal bredd är {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Bildens bredd är för liten ({{ width }}px). Minsta förväntade bredd är {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Bildens höjd är för stor ({{ height }}px). Tillåten maximal bredd är {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Bildens höjd är för liten ({{ height }}px). Minsta förväntade höjd är {{ min_height }}px. This value should be the user current password. Värdet ska vara användarens nuvarande lösenord. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Värdet ska ha exakt {{ limit }} tecken.|Värdet ska ha exakt {{ limit }} tecken. The file was only partially uploaded. Filen laddades bara upp delvis. No file was uploaded. Ingen fil laddades upp. No temporary folder was configured in php.ini. Det finns ingen temporär mapp konfigurerad i php.ini. Cannot write temporary file to disk. Kan inte skriva temporär fil till disken. A PHP extension caused the upload to fail. En PHP extension gjorde att uppladdningen misslyckades. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Den här samlingen ska innehålla {{ limit }} element eller mer.|Den här samlingen ska innehålla {{ limit }} element eller mer. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Den här samlingen ska innehålla {{ limit }} element eller mindre.|Den här samlingen ska innehålla {{ limit }} element eller mindre. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Den här samlingen ska innehålla exakt {{ limit }} element.|Den här samlingen ska innehålla exakt {{ limit }} element. Invalid card number. Ogiltigt kortnummer. Unsupported card type or invalid card number. Okänd korttyp eller ogiltigt kortnummer. This is not a valid International Bank Account Number (IBAN). Det här är inte en giltig International Bank Account Number (IBANK). This value is not a valid ISBN-10. Värdet är inte en giltig ISBN-10. This value is not a valid ISBN-13. Värdet är inte en giltig ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Värdet är varken en giltig ISBN-10 eller en giltig ISBN-13. This value is not a valid ISSN. Värdet är inte en giltig ISSN. This value is not a valid currency. Värdet är inte en giltig valuta. This value should be equal to {{ compared_value }}. Värdet ska vara detsamma som {{ compared_value }}. This value should be greater than {{ compared_value }}. Värdet ska vara större än {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Värdet ska bara större än eller detsamma som {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Värdet ska vara identiskt till {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Värdet ska vara mindre än {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Värdet ska vara mindre än eller detsamma som {{ compared_value }}. This value should not be equal to {{ compared_value }}. Värdet ska inte vara detsamma som {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Värdet ska inte vara identiskt med {{ compared_value_type }} {{ compared_value }}. PK](=A=A2Validator/Resources/translations/validators.gl.xlfnu[ This value should be false. Este valor debería ser falso. This value should be true. Este valor debería ser verdadeiro. This value should be of type {{ type }}. Este valor debería ser de tipo {{ type }}. This value should be blank. Este valor debería estar baleiro. The value you selected is not a valid choice. O valor seleccionado non é unha opción válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Debe seleccionar polo menos {{ limit }} opción.|Debe seleccionar polo menos {{ limit }} opcions. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opcions. One or more of the given values is invalid. Un ou máis dos valores indicados non son válidos. The fields {{ fields }} were not expected. Non se esperaban os campos {{ fields }}. The fields {{ fields }} are missing. Faltan os campos {{ fields }}. This value is not a valid date. Este valor non é unha data válida. This value is not a valid datetime. Este valor non é unha data e hora válidas. This value is not a valid email address. Este valor non é unha dirección de correo electrónico válida. The file could not be found. Non se puido atopar o arquivo. The file is not readable. O arquivo non se pode ler. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é demasiado grande ({{ size }} {{ suffix }}). O tamaño máximo permitido é {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. O tipo mime do arquivo non é válido ({{ type }}). Os tipos mime válidos son {{ types }}. This value should be {{ limit }} or less. Este valor debería ser {{ limit }} ou menos. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Este valor é demasiado longo. Debería ter {{ limit }} carácter ou menos.|Este valor é demasiado longo. Debería ter {{ limit }} caracteres ou menos. This value should be {{ limit }} or more. Este valor debería ser {{ limit }} ou máis. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Este valor é demasiado curto. Debería ter {{ limit }} carácter ou máis.|Este valor é demasiado corto. Debería ter {{ limit }} caracteres ou máis. This value should not be blank. Este valor non debería estar baleiro. This value should not be null. Este valor non debería ser null. This value should be null. Este valor debería ser null. This value is not valid. Este valor non é válido. This value is not a valid time. Este valor non é unha hora válida. This value is not a valid URL. Este valor non é unha URL válida. The two values should be equal. Os dous valores deberían ser iguais. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é demasiado grande. O tamaño máximo permitido é {{ limit }} {{ suffix }}. The file is too large. O arquivo é demasiado grande. The file could not be uploaded. No se puido cargar o arquivo. This value should be a valid number. Este valor debería ser un número válido. This file is not a valid image. O arquivo non é unha imaxe válida. This is not a valid IP address. Isto non é unha dirección IP válida. This value is not a valid language. Este valor non é un idioma válido. This value is not a valid locale. Este valor non é unha localización válida. This value is not a valid country. Este valor non é un país válido. This value is already used. Este valor xa está a ser empregado. The size of the image could not be detected. Non se puido determinar o tamaño da imaxe. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A largura da imaxe é demasiado grande ({{ width }}px). A largura máxima permitida son {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A largura da imaxe é demasiado pequena ({{ width }}px). A largura mínima requerida son {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A altura da imaxe é demasiado grande ({{ height }}px). A altura máxima permitida son {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A altura da imaxe é demasiado pequena ({{ height }}px). A altura mínima requerida son {{ min_height }}px. This value should be the user current password. Este valor debería ser a contrasinal actual do usuario. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor debería ter exactamente {{ limit }} carácter.|Este valor debería ter exactamente {{ limit }} caracteres. The file was only partially uploaded. O arquivo foi só subido parcialmente. No file was uploaded. Non se subiu ningún arquivo. No temporary folder was configured in php.ini. Ningunha carpeta temporal foi configurada en php.ini. Cannot write temporary file to disk. Non se puido escribir o arquivo temporal no disco. A PHP extension caused the upload to fail. Unha extensión de PHP provocou que a subida fallara. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta colección debe conter {{ limit }} elemento ou máis.|Esta colección debe conter {{ limit }} elementos ou máis. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta colección debe conter {{ limit }} elemento ou menos.|Esta colección debe conter {{ limit }} elementos ou menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta colección debe conter exactamente {{ limit }} elemento.|Esta colección debe conter exactamente {{ limit }} elementos. Invalid card number. Número de tarxeta non válido. Unsupported card type or invalid card number. Tipo de tarxeta non soportado ou número de tarxeta non válido. This is not a valid International Bank Account Number (IBAN). Este valor non é un International Bank Account Number (IBAN) válido. This value is not a valid ISBN-10. Este valor non é un ISBN-10 válido. This value is not a valid ISBN-13. Este valor non é un ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor non é nin un ISBN-10 válido nin un ISBN-13 válido. This value is not a valid ISSN. Este valor non é un ISSN válido. This value is not a valid currency. Este valor non é unha moeda válida. This value should be equal to {{ compared_value }}. Este valor debería ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor debería ser maior que {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor debería ser maior ou igual que {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor debería ser identico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor debería ser menor que {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor debería ser menor ou igual que {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor non debería ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor non debería ser identico a {{ compared_value_type }} {{ compared_value }}. PK]v_w,w,2Validator/Resources/translations/validators.hy.xlfnu[ This value should be false. Արժեքը պետք է լինի կեղծ. This value should be true. Արժեքը պետք է լինի ճշմարիտ. This value should be of type {{ type }}. Արժեքը պետք է լինի {{ type }} տեսակի. This value should be blank. Արժեքը պետք է լինի դատարկ. The value you selected is not a valid choice. Ձեր ընտրած արժեքը անթույլատրելի է. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Դուք պետք է ընտրեք ամենաքիչը {{ limit }} տարբերակներ. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Դուք պետք է ընտրեք ոչ ավելի քան {{ limit }} տարբերակներ. One or more of the given values is invalid. Մեկ կամ ավելի տրված արժեքները անթույլատրելի են. The fields {{ fields }} were not expected. {{ fields }} տողերը չէին սպասվում. The fields {{ fields }} are missing. {{ fields }} տողերը բացակայում են. This value is not a valid date. Արժեքը սխալ ամսաթիվ է. This value is not a valid datetime. Ամսաթվի և ժամանակի արժեքը անթույլատրելի է. This value is not a valid email address. Էլ-փոստի արժեքը անթույլատրելի է. The file could not be found. Ֆայլը չի գտնվել. The file is not readable. Ֆայլը անընթեռնելի է. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Ֆայլը չափազանց մեծ է ({{ size }} {{ suffix }}): Մաքսիմալ թույլատրելի չափսը՝ {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. MIME-տեսակը անթույլատրելի է({{ type }}): Ֆայլերի թույլատրելի MIME-տեսակներն են: {{ types }}. This value should be {{ limit }} or less. Արժեքը պետք է լինի {{ limit }} կամ փոքր. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Արժեքը չափազանց երկար է: Պետք է լինի {{ limit }} կամ ավել սիմվոլներ. This value should be {{ limit }} or more. Արժեքը պետ է լինի {{ limit }} կամ շատ. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Արժեքը չափազանց կարճ է: Պետք է լինի {{ limit }} կամ ավելի սիմվոլներ. This value should not be blank. Արժեքը չպետք է դատարկ լինի. This value should not be null. Արժեքը չպետք է լինի null. This value should be null. Արժեքը պետք է լինի null. This value is not valid. Անթույլատրելի արժեք. This value is not a valid time. Ժամանակի արժեքը անթույլատրելի է. This value is not a valid URL. Արժեքը URL չէ. The two values should be equal. Երկու արժեքները պետք է նույնը լինեն. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ֆայլը չափազանց մեծ է: Մաքսիմալ թույլատրելի չափսը {{ limit }} {{ suffix }} է. The file is too large. Ֆայլը չափազանց մեծ է. The file could not be uploaded. Ֆայլը չի կարող բեռնվել. This value should be a valid number. Արժեքը պետք է լինի թիվ. This value is not a valid country. Արժեքը պետք է լինի երկիր. This file is not a valid image. Ֆայլը նկարի թույլատրելի ֆորմատ չէ. This is not a valid IP address. Արժեքը թույլատրելի IP հասցե չէ. This value is not a valid language. Արժեքը թույլատրելի լեզու չէ. This value is not a valid locale. Արժեքը չի հանդիսանում թույլատրելի տեղայնացում. This value is already used. Այդ արժեքը արդեն օգտագործվում է. The size of the image could not be detected. Նկարի չափսերը չստացվեց որոշել. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Նկարի լայնությունը չափազանց մեծ է({{ width }}px). Մաքսիմալ չափն է {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Նկարի լայնությունը չափազանց փոքր է ({{ width }}px). Մինիմալ չափն է {{ min_ width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Նկարի բարձրությունը չափազանց մեծ է ({{ height }}px). Մաքսիմալ չափն է {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Նկարի բարձրությունը չափազանց փոքր է ({{ height }}px). Մինիմալ չափն է {{ min_height }}px. This value should be the user current password. Այս արժեքը պետք է լինի օգտագործողի ներկա ծածկագիրը. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Այս արժեքը պետք է ունենա ճիշտ {{ limit }} սիմվոլներ. PK]sE#AA2Validator/Resources/translations/validators.de.xlfnu[ This value should be false. Dieser Wert sollte false sein. This value should be true. Dieser Wert sollte true sein. This value should be of type {{ type }}. Dieser Wert sollte vom Typ {{ type }} sein. This value should be blank. Dieser Wert sollte leer sein. The value you selected is not a valid choice. Sie haben einen ungültigen Wert ausgewählt. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Sie müssen mindestens {{ limit }} Möglichkeit wählen.|Sie müssen mindestens {{ limit }} Möglichkeiten wählen. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Sie dürfen höchstens {{ limit }} Möglichkeit wählen.|Sie dürfen höchstens {{ limit }} Möglichkeiten wählen. One or more of the given values is invalid. Einer oder mehrere der angegebenen Werte sind ungültig. The fields {{ fields }} were not expected. Die Felder {{ fields }} wurden nicht erwartet. The fields {{ fields }} are missing. Die erwarteten Felder {{ fields }} fehlen. This value is not a valid date. Dieser Wert entspricht keiner gültigen Datumsangabe. This value is not a valid datetime. Dieser Wert entspricht keiner gültigen Datums- und Zeitangabe. This value is not a valid email address. Dieser Wert ist keine gültige E-Mail-Adresse. The file could not be found. Die Datei wurde nicht gefunden. The file is not readable. Die Datei ist nicht lesbar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Die Datei ist zu groß ({{ size }} {{ suffix }}). Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Der Dateityp ist ungültig ({{ type }}). Erlaubte Dateitypen sind {{ types }}. This value should be {{ limit }} or less. Dieser Wert sollte kleiner oder gleich {{ limit }} sein. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben. This value should be {{ limit }} or more. Dieser Wert sollte größer oder gleich {{ limit }} sein. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben. This value should not be blank. Dieser Wert sollte nicht leer sein. This value should not be null. Dieser Wert sollte nicht null sein. This value should be null. Dieser Wert sollte null sein. This value is not valid. Dieser Wert ist nicht gültig. This value is not a valid time. Dieser Wert entspricht keiner gültigen Zeitangabe. This value is not a valid URL. Dieser Wert ist keine gültige URL. The two values should be equal. Die beiden Werte sollten identisch sein. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Die Datei ist zu groß. Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}. The file is too large. Die Datei ist zu groß. The file could not be uploaded. Die Datei konnte nicht hochgeladen werden. This value should be a valid number. Dieser Wert sollte eine gültige Zahl sein. This file is not a valid image. Diese Datei ist kein gültiges Bild. This is not a valid IP address. Dies ist keine gültige IP-Adresse. This value is not a valid language. Dieser Wert entspricht keiner gültigen Sprache. This value is not a valid locale. Dieser Wert entspricht keinem gültigen Gebietsschema. This value is not a valid country. Dieser Wert entspricht keinem gültigen Land. This value is already used. Dieser Wert wird bereits verwendet. The size of the image could not be detected. Die Größe des Bildes konnte nicht ermittelt werden. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Die Bildbreite ist zu groß ({{ width }}px). Die maximal zulässige Breite beträgt {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Die Bildbreite ist zu gering ({{ width }}px). Die erwartete Mindestbreite beträgt {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Die Bildhöhe ist zu groß ({{ height }}px). Die maximal zulässige Höhe beträgt {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Die Bildhöhe ist zu gering ({{ height }}px). Die erwartete Mindesthöhe beträgt {{ min_height }}px. This value should be the user current password. Dieser Wert sollte dem aktuellen Benutzerpasswort entsprechen. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Dieser Wert sollte genau {{ limit }} Zeichen lang sein.|Dieser Wert sollte genau {{ limit }} Zeichen lang sein. The file was only partially uploaded. Die Datei wurde nur teilweise hochgeladen. No file was uploaded. Es wurde keine Datei hochgeladen. No temporary folder was configured in php.ini. Es wurde kein temporärer Ordner in der php.ini konfiguriert. Cannot write temporary file to disk. Kann die temporäre Datei nicht speichern. A PHP extension caused the upload to fail. Eine PHP-Erweiterung verhinderte den Upload. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Diese Sammlung sollte genau {{ limit }} Element beinhalten.|Diese Sammlung sollte genau {{ limit }} Elemente beinhalten. Invalid card number. Ungültige Kartennummer. Unsupported card type or invalid card number. Nicht unterstützer Kartentyp oder ungültige Kartennummer. This is not a valid International Bank Account Number (IBAN). Dieser Wert ist keine gültige IBAN-Kontonummer. This value is not a valid ISBN-10. Dieser Wert entspricht keiner gültigen ISBN-10. This value is not a valid ISBN-13. Dieser Wert entspricht keiner gültigen ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Dieser Wert ist weder eine gültige ISBN-10 noch eine gültige ISBN-13. This value is not a valid ISSN. Dieser Wert ist keine gültige ISSN. This value is not a valid currency. Dieser Wert ist keine gültige Währung. This value should be equal to {{ compared_value }}. Dieser Wert sollte gleich {{ compared_value }} sein. This value should be greater than {{ compared_value }}. Dieser Wert sollte größer als {{ compared_value }} sein. This value should be greater than or equal to {{ compared_value }}. Dieser Wert sollte größer oder gleich {{ compared_value }} sein. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Dieser Wert sollte identisch sein mit {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Dieser Wert sollte kleiner als {{ compared_value }} sein. This value should be less than or equal to {{ compared_value }}. Dieser Wert sollte kleiner oder gleich {{ compared_value }} sein. This value should not be equal to {{ compared_value }}. Dieser Wert sollte nicht {{ compared_value }} sein. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Dieser Wert sollte nicht identisch sein mit {{ compared_value_type }} {{ compared_value }}. PK]-uCuC2Validator/Resources/translations/validators.sk.xlfnu[ This value should be false. Táto hodnota by mala byť nastavená na false. This value should be true. Táto hodnota by mala byť nastavená na true. This value should be of type {{ type }}. Táto hodnota by mala byť typu {{ type }}. This value should be blank. Táto hodnota by mala byť prázdna. The value you selected is not a valid choice. Táto hodnota by mala byť jednou z poskytnutých možností. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Mali by ste vybrať minimálne {{ limit }} možnosť.|Mali by ste vybrať minimálne {{ limit }} možnosti.|Mali by ste vybrať minimálne {{ limit }} možností. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Mali by ste vybrať najviac {{ limit }} možnosť.|Mali by ste vybrať najviac {{ limit }} možnosti.|Mali by ste vybrať najviac {{ limit }} možností. One or more of the given values is invalid. Niektoré z uvedených hodnôt sú neplatné. The fields {{ fields }} were not expected. Polia {{ fields }} neboli očakávané. The fields {{ fields }} are missing. Chýbajú polia {{ fields }} . This value is not a valid date. Tato hodnota nemá platný formát dátumu. This value is not a valid datetime. Táto hodnota nemá platný formát dátumu a času. This value is not a valid email address. Táto hodnota nie je platná emailová adresa. The file could not be found. Súbor sa nenašiel. The file is not readable. Súbor nie je čitateľný. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Súbor je príliš veľký ({{ size }} {{ suffix }}). Maximálna povolená veľkosť je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Súbor typu ({{ type }}) nie je podporovaný. Podporované typy sú {{ types }}. This value should be {{ limit }} or less. Táto hodnota by mala byť {{ limit }} alebo menej. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znak.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znaky.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znakov. This value should be {{ limit }} or more. Táto hodnota by mala byť viac ako {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znak.|Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znaky.|Táto hodnota je príliš krátka. Minimálny počet znakov je {{ limit }}. This value should not be blank. Táto hodnota by mala byť vyplnená. This value should not be null. Táto hodnota by nemala byť null. This value should be null. Táto hodnota by mala byť null. This value is not valid. Táto hodnota nie je platná. This value is not a valid time. Tato hodnota nemá správny formát času. This value is not a valid URL. Táto hodnota nie je platnou URL adresou. The two values should be equal. Tieto dve hodnoty by mali byť rovnaké. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Súbor je príliš veľký. Maximálna povolená veľkosť je {{ limit }} {{ suffix }}. The file is too large. Súbor je príliš veľký. The file could not be uploaded. Súbor sa nepodarilo nahrať. This value should be a valid number. Táto hodnota by mala byť číslo. This file is not a valid image. Tento súbor nie je obrázok. This is not a valid IP address. Toto nie je platná IP adresa. This value is not a valid language. Tento jazyk neexistuje. This value is not a valid locale. Táto lokalizácia neexistuje. This value is not a valid country. Táto krajina neexistuje. This value is already used. Táto hodnota sa už používa. The size of the image could not be detected. Nepodarilo sa zistiť rozmery obrázku. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Obrázok je príliš široký ({{ width }}px). Maximálna povolená šírka obrázku je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Obrázok je príliš úzky ({{ width }}px). Minimálna šírka obrázku by mala byť {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. >Obrázok je príliš vysoký ({{ height }}px). Maximálna povolená výška obrázku je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Obrázok je príliš nízky ({{ height }}px). Minimálna výška obrázku by mala byť {{ min_height }}px. This value should be the user current password. Táto hodnota by mala byť aktuálne heslo používateľa. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Táto hodnota by mala mať presne {{ limit }} znak.|Táto hodnota by mala mať presne {{ limit }} znaky.|Táto hodnota by mala mať presne {{ limit }} znakov. The file was only partially uploaded. Bola nahraná len časť súboru. No file was uploaded. Žiadny súbor nebol nahraný. No temporary folder was configured in php.ini. V php.ini nie je nastavená cesta k adresáru pre dočasné súbory. Cannot write temporary file to disk. Dočasný súbor sa nepodarilo zapísať na disk. A PHP extension caused the upload to fail. Rozšírenie PHP zabránilo nahraniu súboru. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Táto kolekcia by mala obsahovať aspoň {{ limit }} prvok alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvky alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvkov alebo viac. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Táto kolekcia by mala maximálne {{ limit }} prvok.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvky.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvkov. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Táto kolekcia by mala obsahovať presne {{ limit }} prvok.|Táto kolekcia by mala obsahovať presne {{ limit }} prvky.|Táto kolekcia by mala obsahovať presne {{ limit }} prvkov. Invalid card number. Neplatné číslo karty. Unsupported card type or invalid card number. Nepodporovaný typ karty alebo neplatné číslo karty. This is not a valid International Bank Account Number (IBAN). Toto je neplatný IBAN. This value is not a valid ISBN-10. Táto hodnota je neplatné ISBN-10. This value is not a valid ISBN-13. Táto hodnota je neplatné ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Táto hodnota nie je platné ISBN-10 ani ISBN-13. This value is not a valid ISSN. Táto hodnota nie je platné ISSN. This value is not a valid currency. Táto hodnota nie je platná mena. This value should be equal to {{ compared_value }}. Táto hodnota by mala byť rovná {{ compared_value }}. This value should be greater than {{ compared_value }}. Táto hodnota by mala byť väčšia ako {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Táto hodnota by mala byť väčšia alebo rovná {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Táto hodnota by mala byť typu {{ compared_value_type }} a zároveň by mala byť rovná {{ compared_value }}. This value should be less than {{ compared_value }}. Táto hodnota by mala byť menšia ako {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Táto hodnota by mala byť menšia alebo rovná {{ compared_value }}. This value should not be equal to {{ compared_value }}. Táto hodnota by nemala byť rovná {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Táto hodnota by nemala byť typu {{ compared_value_type }} a zároveň by nemala byť rovná {{ compared_value }}. PK] )BB2Validator/Resources/translations/validators.cs.xlfnu[ This value should be false. Tato hodnota musí být nepravdivá (false). This value should be true. Tato hodnota musí být pravdivá (true). This value should be of type {{ type }}. Tato hodnota musí být typu {{ type }}. This value should be blank. Tato hodnota musí být prázdná. The value you selected is not a valid choice. Vybraná hodnota není platnou možností. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Musí být vybrána nejméně {{ limit }} možnost.|Musí být vybrány nejméně {{ limit }} možnosti.|Musí být vybráno nejméně {{ limit }} možností. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Musí být vybrána maximálně {{ limit }} možnost.|Musí být vybrány maximálně {{ limit }} možnosti.|Musí být vybráno maximálně {{ limit }} možností. One or more of the given values is invalid. Některé z uvedených hodnot jsou neplatné. The fields {{ fields }} were not expected. Neočekávaná pole {{ fields }}. The fields {{ fields }} are missing. Chybí následující pole {{ fields }}. This value is not a valid date. Tato hodnota není platné datum. This value is not a valid datetime. Tato hodnota není platné datum s časovým údajem. This value is not a valid email address. Tato hodnota není platná e-mailová adresa. The file could not be found. Soubor nebyl nalezen. The file is not readable. Soubor je nečitelný. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Soubor je příliš velký ({{ size }} {{ suffix }}). Maximální povolená velikost souboru je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Neplatný mime typ souboru ({{ type }}). Povolené mime typy souborů jsou {{ types }}. This value should be {{ limit }} or less. Tato hodnota musí být {{ limit }} nebo méně. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znak.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaky.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaků. This value should be {{ limit }} or more. Tato hodnota musí být {{ limit }} nebo více. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znak.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaky.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaků. This value should not be blank. Tato hodnota nesmí být prázdná. This value should not be null. Tato hodnota nesmí být prázdná. This value should be null. Tato hodnota musí být prázdná. This value is not valid. Tato hodnota není platná. This value is not a valid time. Tato hodnota není platný časový údaj. This value is not a valid URL. Tato hodnota není platná URL adresa. The two values should be equal. Tyto dvě hodnoty musí být stejné. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Soubor je příliš velký. Maximální povolená velikost souboru je {{ limit }} {{ suffix }}. The file is too large. Soubor je příliš velký. The file could not be uploaded. Soubor se nepodařilo nahrát. This value should be a valid number. Tato hodnota musí být číslo. This file is not a valid image. Tento soubor není obrázek. This is not a valid IP address. Toto není platná IP adresa. This value is not a valid language. Tento jazyk neexistuje. This value is not a valid locale. Tato lokalizace neexistuje. This value is not a valid country. Tato země neexistuje. This value is already used. Tato hodnota je již používána. The size of the image could not be detected. Nepodařily se zjistit rozměry obrázku. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Obrázek je příliš široký ({{ width }}px). Maximální povolená šířka obrázku je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Obrázek je příliš úzký ({{ width }}px). Minimální šířka musí být {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Obrázek je příliš vysoký ({{ height }}px). Maximální povolená výška obrázku je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Obrázek je příliš nízký ({{ height }}px). Minimální výška obrázku musí být {{ min_height }}px. This value should be the user current password. Tato hodnota musí být aktuální heslo uživatele. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Tato hodnota musí mít přesně {{ limit }} znak.|Tato hodnota musí mít přesně {{ limit }} znaky.|Tato hodnota musí mít přesně {{ limit }} znaků. The file was only partially uploaded. Byla nahrána jen část souboru. No file was uploaded. Žádný soubor nebyl nahrán. No temporary folder was configured in php.ini. V php.ini není nastavena cesta k adresáři pro dočasné soubory. Cannot write temporary file to disk. Dočasný soubor se nepodařilo zapsat na disk. A PHP extension caused the upload to fail. Rozšíření PHP zabránilo nahrání souboru. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Tato kolekce musí obsahovat minimálně {{ limit }} prvek.|Tato kolekce musí obsahovat minimálně {{ limit }} prvky.|Tato kolekce musí obsahovat minimálně {{ limit }} prvků. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Tato kolekce musí obsahovat maximálně {{ limit }} prvek.|Tato kolekce musí obsahovat maximálně {{ limit }} prvky.|Tato kolekce musí obsahovat maximálně {{ limit }} prvků. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Tato kolekce musí obsahovat přesně {{ limit }} prvek.|Tato kolekce musí obsahovat přesně {{ limit }} prvky.|Tato kolekce musí obsahovat přesně {{ limit }} prvků. Invalid card number. Neplatné číslo karty. Unsupported card type or invalid card number. Nepodporovaný typ karty nebo neplatné číslo karty. This is not a valid International Bank Account Number (IBAN). Toto je neplatný IBAN. This value is not a valid ISBN-10. Tato hodnota není platné ISBN-10. This value is not a valid ISBN-13. Tato hodnota není platné ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Tato hodnota není platné ISBN-10 ani ISBN-13. This value is not a valid ISSN. Tato hodnota není platné ISSN. This value is not a valid currency. Tato měna neexistuje. This value should be equal to {{ compared_value }}. Tato hodnota musí být rovna {{ compared_value }}. This value should be greater than {{ compared_value }}. Tato hodnota musí být větší než {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Tato hodnota musí být větší nebo rovna {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Tato hodnota musí být typu {{ compared_value_type }} a zároveň musí být rovna {{ compared_value }}. This value should be less than {{ compared_value }}. Tato hodnota musí být menší než {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Tato hodnota musí být menší nebo rovna {{ compared_value }}. This value should not be equal to {{ compared_value }}. Tato hodnota nesmí být rovna {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Tato hodnota nesmí být typu {{ compared_value_type }} a zároveň nesmí být rovna {{ compared_value }}. PK](ee2Validator/Resources/translations/validators.nb.xlfnu[ This value should be false. Verdien skal være falsk. This value should be true. Verdien skal være sann. This value should be of type {{ type }}. Verdien skal være av typen {{ type }}. This value should be blank. Verdien skal være blank. The value you selected is not a valid choice. Verdien skal være en av de gitte valg. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du skal velge minst {{ limit }} valg. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan maks velge {{ limit }} valg. One or more of the given values is invalid. En eller flere av de oppgitte verdier er ugyldige. The fields {{ fields }} were not expected. Feltene {{ fields }} var ikke forventet. The fields {{ fields }} are missing. Feltene {{ fields }} mangler. This value is not a valid date. Verdien er ikke en gyldig dato. This value is not a valid datetime. Verdien er ikke en gyldig dato og tid. This value is not a valid email address. Verdien er ikke en gyldig e-mail adresse. The file could not be found. Filen kunne ikke finnes. The file is not readable. Filen kan ikke leses. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor ({{ size }} {{ suffix }}). Tilatte maksimale størrelse {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mimetypen av filen er ugyldig ({{ type }}). Tilatte mimetyper er {{ types }}. This value should be {{ limit }} or less. Verdien skal være {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Verdien er for lang. Den skal ha {{ limit }} bokstaver eller mindre. This value should be {{ limit }} or more. Verdien skal være {{ limit }} eller mer. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Verdien er for kort. Den skal ha {{ limit }} tegn eller flere. This value should not be blank. Verdien må ikke være blank. This value should not be null. Verdien må ikke være tom (null). This value should be null. Verdien skal være tom (null). This value is not valid. Verdien er ikke gyldig. This value is not a valid time. Verdien er ikke en gyldig tid. This value is not a valid URL. Verdien er ikke en gyldig URL. The two values should be equal. De to verdier skal være ens. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}. The file is too large. Filen er for stor. The file could not be uploaded. Filen kunne ikke lastes opp. This value should be a valid number. Denne verdi skal være et gyldig tall. This file is not a valid image. Denne filen er ikke et gyldig bilde. This is not a valid IP address. Dette er ikke en gyldig IP adresse. This value is not a valid language. Denne verdi er ikke et gyldig språk. This value is not a valid locale. Denne verdi er ikke en gyldig lokalitet. This value is not a valid country. Denne verdi er ikke et gyldig land. PK]6%=%=5Validator/Resources/translations/validators.zh_CN.xlfnu[ This value should be false. 该变量的值应为 false 。 This value should be true. 该变量的值应为 true 。 This value should be of type {{ type }}. 该变量的类型应为 {{ type }} 。 This value should be blank. 该变量值应为空。 The value you selected is not a valid choice. 选定变量的值不是有效的选项。 You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. 您至少要选择 {{ limit }} 个选项。 You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. 您最多能选择 {{ limit }} 个选项。 One or more of the given values is invalid. 一个或者多个给定的值无效。 The fields {{ fields }} were not expected. 非预期字段 {{ fields }} 。 The fields {{ fields }} are missing. 遗漏字段 {{ fields }} 。 This value is not a valid date. 该值不是一个有效的日期(date)。 This value is not a valid datetime. 该值不是一个有效的日期时间(datetime)。 This value is not a valid email address. 该值不是一个有效的邮件地址。 The file could not be found. 文件未找到。 The file is not readable. 文件不可读。 The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. 文件太大 ({{ size }} {{ suffix }})。文件大小不可以超过 {{ limit }} {{ suffix }} 。 The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. 无效的文件类型 ({{ type }}) 。允许的文件类型有 {{ types }} 。 This value should be {{ limit }} or less. 这个变量的值应该小于或等于 {{ limit }}。 This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. 字符串太长,长度不可超过 {{ limit }} 个字符。 This value should be {{ limit }} or more. 该变量的值应该大于或等于 {{ limit }}。 This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. 字符串太短,长度不可少于 {{ limit }} 个字符。 This value should not be blank. 该变量不应为空。 This value should not be null. 该变量不应为 null 。 This value should be null. 该变量应为空 null 。 This value is not valid. 该变量值无效 。 This value is not a valid time. 该值不是一个有效的时间。 This value is not a valid URL. 该值不是一个有效的 URL 。 The two values should be equal. 这两个变量的值应该相等。 The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. 文件太大,文件大小不可以超过 {{ limit }} {{ suffix }}。 The file is too large. 文件太大。 The file could not be uploaded. 无法上传此文件。 This value should be a valid number. 该值应该为有效的数字。 This value is not a valid country. 该值不是有效的国家名。 This file is not a valid image. 该文件不是有效的图片。 This is not a valid IP address. 该值不是有效的IP地址。 This value is not a valid language. 该值不是有效的语言名。 This value is not a valid locale. 该值不是有效的区域值(locale)。 This value is already used. 该值已经被使用。 The size of the image could not be detected. 不能解析图片大小。 The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. 图片太宽 ({{ width }}px),最大宽度为 {{ max_width }}px 。 The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. 图片宽度不够 ({{ width }}px),最小宽度为 {{ min_width }}px 。 The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. 图片太高 ({{ height }}px),最大高度为 {{ max_height }}px 。 The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. 图片高度不够 ({{ height }}px),最小高度为 {{ min_height }}px 。 This value should be the user current password. 该变量的值应为用户当前的密码。 This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. 该变量应为 {{ limit }} 个字符。 The file was only partially uploaded. 该文件的上传不完整。 No file was uploaded. 没有上传任何文件。 No temporary folder was configured in php.ini. php.ini 里没有配置临时文件目录。 Cannot write temporary file to disk. 临时文件写入磁盘失败。 A PHP extension caused the upload to fail. 某个 PHP 扩展造成上传失败。 This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. 该集合最少应包含 {{ limit }} 个元素。 This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. 该集合最多包含 {{ limit }} 个元素。 This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. 该集合应包含 {{ limit }} 个元素 element 。 Invalid card number. 无效的信用卡号。 Unsupported card type or invalid card number. 不支持的信用卡类型或无效的信用卡号。 This is not a valid International Bank Account Number (IBAN). 该值不是有效的国际银行帐号(IBAN)。 This value is not a valid ISBN-10. 该值不是有效的10位国际标准书号(ISBN-10)。 This value is not a valid ISBN-13. 该值不是有效的13位国际标准书号(ISBN-13)。 This value is neither a valid ISBN-10 nor a valid ISBN-13. 该值不是有效的国际标准书号(ISBN-10 或 ISBN-13)。 This value is not a valid ISSN. 该值不是有效的国际标准期刊号(ISSN)。 This value is not a valid currency. 该值不是有效的货币名(currency)。 This value should be equal to {{ compared_value }}. 该值应等于 {{ compared_value }} 。 This value should be greater than {{ compared_value }}. 该值应大于 {{ compared_value }} 。 This value should be greater than or equal to {{ compared_value }}. 该值应大于或等于 {{ compared_value }} 。 This value should be identical to {{ compared_value_type }} {{ compared_value }}. 该值应与 {{ compared_value_type }} {{ compared_value }} 相同。 This value should be less than {{ compared_value }}. 该值应小于 {{ compared_value }} 。 This value should be less than or equal to {{ compared_value }}. 该值应小于或等于 {{ compared_value }} 。 This value should not be equal to {{ compared_value }}. 该值不应先等于 {{ compared_value }} 。 This value should not be identical to {{ compared_value_type }} {{ compared_value }}. 该值不应与 {{ compared_value_type }} {{ compared_value }} 相同。 PK]wX@X@2Validator/Resources/translations/validators.hr.xlfnu[ This value should be false. Ova vrijednost treba biti netočna (false). This value should be true. Ova vrijednost treba biti točna (true). This value should be of type {{ type }}. Ova vrijednost treba biti tipa {{ type }}. This value should be blank. Ova vrijednost treba biti prazna. The value you selected is not a valid choice. Ova vrijednost treba biti jedna od ponuđenih. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Izaberite barem {{ limit }} mogućnosti. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Izaberite najviše {{ limit }} mogućnosti. One or more of the given values is invalid. Jedna ili više danih vrijednosti nije ispravna. The fields {{ fields }} were not expected. Polja {{ fields }} nisu bila očekivana. The fields {{ fields }} are missing. Polja {{ fields }} nedostaju. This value is not a valid date. Ova vrijednost nije ispravan datum. This value is not a valid datetime. Ova vrijednost nije ispravan datum-vrijeme. This value is not a valid email address. Ova vrijednost nije ispravna e-mail adresa. The file could not be found. Datoteka ne može biti pronađena. The file is not readable. Datoteka nije čitljiva. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime tip datoteke nije ispravan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}. This value should be {{ limit }} or less. Ova vrijednost treba biti {{ limit }} ili manje. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ova vrijednost je predugačka. Treba imati {{ limit }} znakova ili manje. This value should be {{ limit }} or more. Ova vrijednost treba biti {{ limit }} ili više. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ova vrijednost je prekratka. Treba imati {{ limit }} znakova ili više. This value should not be blank. Ova vrijednost ne smije biti prazna. This value should not be null. Ova vrijednost ne smije biti null. This value should be null. Ova vrijednost treba biti null. This value is not valid. Ova vrijednost nije ispravna. This value is not a valid time. Ova vrijednost nije ispravno vrijeme. This value is not a valid URL. Ova vrijednost nije ispravan URL. The two values should be equal. Obje vrijednosti trebaju biti jednake. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ova datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The file is too large. Ova datoteka je prevelika. The file could not be uploaded. Ova datoteka ne može biti prenesena. This value should be a valid number. Ova vrijednost treba biti ispravan broj. This file is not a valid image. Ova datoteka nije ispravna slika. This is not a valid IP address. Ovo nije ispravna IP adresa. This value is not a valid language. Ova vrijednost nije ispravan jezik. This value is not a valid locale. Ova vrijednost nije ispravana regionalna oznaka. This value is not a valid country. Ova vrijednost nije ispravna zemlja. This value is already used. Ova vrijednost je već iskorištena. The size of the image could not be detected. Veličina slike se ne može odrediti. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Širina slike je prevelika ({{ width }}px). Najveća dozvoljena širina je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Visina slike je prevelika ({{ height }}px). Najveća dozvoljena visina je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px. This value should be the user current password. Ova vrijednost treba biti trenutna korisnička lozinka. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ova vrijednost treba imati točno {{ limit }} znakova. The file was only partially uploaded. Datoteka je samo djelomično prenesena. No file was uploaded. Niti jedna datoteka nije prenesena. No temporary folder was configured in php.ini. U php.ini datoteci nije konfiguriran privremeni folder. Cannot write temporary file to disk. Ne mogu zapisati privremenu datoteku na disk. A PHP extension caused the upload to fail. Prijenos datoteke nije uspio zbog PHP ekstenzije. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ova kolekcija treba sadržavati točno {{ limit }} element.|Ova kolekcija treba sadržavati točno {{ limit }} elementa.|Ova kolekcija treba sadržavati točno {{ limit }} elemenata. Invalid card number. Neispravan broj kartice. Unsupported card type or invalid card number. Neispravan broj kartice ili tip kartice nije podržan. This is not a valid International Bank Account Number (IBAN). Ova vrijednost nije ispravan međunarodni broj bankovnog računa (IBAN). This value is not a valid ISBN-10. Ova vrijednost nije ispravan ISBN-10. This value is not a valid ISBN-13. Ova vrijednost nije ispravan ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ova vrijednost nije ispravan ISBN-10 niti ISBN-13. This value is not a valid ISSN. Ova vrijednost nije ispravan ISSN. This value is not a valid currency. Ova vrijednost nije ispravna valuta. This value should be equal to {{ compared_value }}. Ova vrijednost bi trebala biti jednaka {{ compared_value }}. This value should be greater than {{ compared_value }}. Ova vrijednost bi trebala biti veća od {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ova vrijednost bi trebala biti veća ili jednaka od {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ova vrijednost bi trebala biti {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ova vrijednost bi trebala biti manja od {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ova vrijednost bi trebala biti manja ili jednaka {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ova vrijednost ne bi trebala biti {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ova vrijednost ne bi trebala biti {{ compared_value_type }} {{ compared_value }}. PK]93XaoAoA2Validator/Resources/translations/validators.hu.xlfnu[ This value should be false. Ennek az értéknek hamisnak kell lennie. This value should be true. Ennek az értéknek igaznak kell lennie. This value should be of type {{ type }}. Ennek az értéknek {{ type }} típusúnak kell lennie. This value should be blank. Ennek az értéknek üresnek kell lennie. The value you selected is not a valid choice. A választott érték érvénytelen. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Legalább {{ limit }} értéket kell kiválasztani.|Legalább {{ limit }} értéket kell kiválasztani. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Legfeljebb {{ limit }} értéket lehet kiválasztani.|Legfeljebb {{ limit }} értéket lehet kiválasztani. One or more of the given values is invalid. A megadott értékek közül legalább egy érvénytelen. The fields {{ fields }} were not expected. Váratlan mezők: {{ fields }}. The fields {{ fields }} are missing. A következő mezők hiányoznak: {{ fields }}. This value is not a valid date. Ez az érték nem egy érvényes dátum. This value is not a valid datetime. Ez az érték nem egy érvényes időpont. This value is not a valid email address. Ez az érték nem egy érvényes e-mail cím. The file could not be found. A fájl nem található. The file is not readable. A fájl nem olvasható. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. A fájl túl nagy ({{ size }} {{ suffix }}). A legnagyobb megengedett méret {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. A fájl mime típusa érvénytelen ({{ type }}). Az engedélyezett mime típusok: {{ types }}. This value should be {{ limit }} or less. Ez az érték legfeljebb {{ limit }} lehet. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat.|Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat. This value should be {{ limit }} or more. Ez az érték legalább {{ limit }} kell legyen. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia.|Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia. This value should not be blank. Ez az érték nem lehet üres. This value should not be null. Ez az érték nem lehet null. This value should be null. Ennek az értéknek nullnak kell lennie. This value is not valid. Ez az érték nem érvényes. This value is not a valid time. Ez az érték nem egy érvényes időpont. This value is not a valid URL. Ez az érték nem egy érvényes URL. The two values should be equal. A két értéknek azonosnak kell lennie. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. A fájl túl nagy. A megengedett maximális méret: {{ limit }} {{ suffix }}. The file is too large. A fájl túl nagy. The file could not be uploaded. A fájl nem tölthető fel. This value should be a valid number. Ennek az értéknek érvényes számnak kell lennie. This file is not a valid image. Ez a fájl nem egy érvényes kép. This is not a valid IP address. Ez az érték nem egy érvényes IP cím. This value is not a valid language. Ez az érték nem egy érvényes nyelv. This value is not a valid locale. Ez az érték nem egy érvényes területi beállítás. This value is not a valid country. Ez az érték nem egy érvényes ország. This value is already used. Ez az érték már használatban van. The size of the image could not be detected. A kép méretét nem lehet megállapítani. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A kép szélessége túl nagy ({{ width }}px). A megengedett legnagyobb szélesség {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A kép szélessége túl kicsi ({{ width }}px). Az elvárt legkisebb szélesség {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A kép magassága túl nagy ({{ height }}px). A megengedett legnagyobb magasság {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A kép magassága túl kicsi ({{ height }}px). Az elvárt legkisebb magasság {{ min_height }}px. This value should be the user current password. Ez az érték a felhasználó jelenlegi jelszavával kell megegyezzen. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia.|Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia. The file was only partially uploaded. A fájl csak részben lett feltöltve. No file was uploaded. Nem lett fájl feltöltve. No temporary folder was configured in php.ini. Nincs ideiglenes könyvtár beállítva a php.ini-ben. Cannot write temporary file to disk. Az ideiglenes fájl nem írható a lemezre. A PHP extension caused the upload to fail. Egy PHP bővítmény miatt a feltöltés nem sikerült. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat.|Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia. Invalid card number. Érvénytelen kártyaszám. Unsupported card type or invalid card number. Nem támogatott kártyatípus vagy érvénytelen kártyaszám. This is not a valid International Bank Account Number (IBAN). Érvénytelen nemzetközi bankszámlaszám (IBAN). This value is not a valid ISBN-10. Ez az érték nem egy érvényes ISBN-10. This value is not a valid ISBN-13. Ez az érték nem egy érvényes ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ez az érték nem egy érvényes ISBN-10 vagy ISBN-13. This value is not a valid ISSN. Ez az érték nem egy érvényes ISSN. This value is not a valid currency. Ez az érték nem egy érvényes pénznem. This value should be equal to {{ compared_value }}. Ez az érték legyen {{ compared_value }}. This value should be greater than {{ compared_value }}. Ez az érték nagyobb legyen mint {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ez az érték nagyobb vagy egyenlő legyen mint {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ez az érték ugyanolyan legyen mint {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ez az érték kisebb legyen mint {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ez az érték kisebb vagy egyenlő legyen mint {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ez az érték ne legyen {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ez az érték ne legyen ugyanolyan mint {{ compared_value_type }} {{ compared_value }}. PK]1ar==5Validator/Resources/translations/validators.zh_TW.xlfnu[ This value should be false. 該變數的值應為 false 。 This value should be true. 該變數的值應為 true 。 This value should be of type {{ type }}. 該變數的類型應為 {{ type }} 。 This value should be blank. 該變數應為空。 The value you selected is not a valid choice. 選定變數的值不是有效的選項。 You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. 您至少要選擇 {{ limit }} 個選項。 You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. 您最多能選擇 {{ limit }} 個選項。 One or more of the given values is invalid. 一個或者多個給定的值無效。 The fields {{ fields }} were not expected. 非預期的欄位 {{ fields }} 。 The fields {{ fields }} are missing. 缺少的欄位 {{ fields }} 。 This value is not a valid date. 該值不是一個有效的日期(date)。 This value is not a valid datetime. 該值不是一個有效的日期時間(datetime)。 This value is not a valid email address. 該值不是一個有效的郵件地址。 The file could not be found. 找不到檔案。 The file is not readable. 無法讀取檔案。 The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. 檔案太大 ({{ size }} {{ suffix }})。檔案大小不可以超過 {{ limit }} {{ suffix }} 。 The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. 無效的檔案類型 ({{ type }}) 。允許的檔案類型有 {{ types }} 。 This value should be {{ limit }} or less. 這個變數的值應該小於或等於 {{ limit }}。 This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. 字串太長,長度不可超過 {{ limit }} 個字元。 This value should be {{ limit }} or more. 該變數的值應該大於或等於 {{ limit }}。 This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. 字串太短,長度不可少於 {{ limit }} 個字元。 This value should not be blank. 該變數不應為空白。 This value should not be null. 該值不應為 null 。 This value should be null. 該值應為 null 。 This value is not valid. 無效的數值 。 This value is not a valid time. 該值不是一個有效的時間。 This value is not a valid URL. 該值不是一個有效的 URL 。 The two values should be equal. 這兩個變數的值應該相等。 The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. 檔案太大,檔案大小不可以超過 {{ limit }} {{ suffix }}。 The file is too large. 檔案太大。 The file could not be uploaded. 無法上傳此檔案。 This value should be a valid number. 該值應該為有效的數字。 This value is not a valid country. 該值不是有效的國家名。 This file is not a valid image. 該檔案不是有效的圖片。 This is not a valid IP address. 該值不是有效的IP地址。 This value is not a valid language. 該值不是有效的語言名。 This value is not a valid locale. 該值不是有效的區域值(locale)。 This value is already used. 該值已經被使用。 The size of the image could not be detected. 不能解析圖片大小。 The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. 圖片太寬 ({{ width }}px),最大寬度為 {{ max_width }}px 。 The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. 圖片寬度不夠 ({{ width }}px),最小寬度為 {{ min_width }}px 。 The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. 圖片太高 ({{ height }}px),最大高度為 {{ max_height }}px 。 The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. 圖片高度不夠 ({{ height }}px),最小高度為 {{ min_height }}px 。 This value should be the user current password. 該變數的值應為用戶目前的密碼。 This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. 該變數應為 {{ limit }} 個字元。 The file was only partially uploaded. 該檔案的上傳不完整。 No file was uploaded. 沒有上傳任何檔案。 No temporary folder was configured in php.ini. php.ini 裡沒有配置臨時目錄。 Cannot write temporary file to disk. 暫存檔寫入磁碟失敗。 A PHP extension caused the upload to fail. 某個 PHP 擴展造成上傳失敗。 This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. 該集合最少應包含 {{ limit }} 個元素。 This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. 該集合最多包含 {{ limit }} 個元素。 This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. 該集合應包含 {{ limit }} 個元素 element 。 Invalid card number. 無效的信用卡號。 Unsupported card type or invalid card number. 不支援的信用卡類型或無效的信用卡號。 This is not a valid International Bank Account Number (IBAN). 該值不是有效的國際銀行帳號(IBAN)。 This value is not a valid ISBN-10. 該值不是有效的10位國際標準書號(ISBN-10)。 This value is not a valid ISBN-13. 該值不是有效的13位國際標準書號(ISBN-13)。 This value is neither a valid ISBN-10 nor a valid ISBN-13. 該值不是有效的國際標準書號(ISBN-10 或 ISBN-13)。 This value is not a valid ISSN. 該值不是有效的國際標準期刊號(ISSN)。 This value is not a valid currency. 該值不是有效的貨幣名(currency)。 This value should be equal to {{ compared_value }}. 該值應等於 {{ compared_value }} 。 This value should be greater than {{ compared_value }}. 該值應大於 {{ compared_value }} 。 This value should be greater than or equal to {{ compared_value }}. 該值應大於或等於 {{ compared_value }} 。 This value should be identical to {{ compared_value_type }} {{ compared_value }}. 該值應與 {{ compared_value_type }} {{ compared_value }} 相同。 This value should be less than {{ compared_value }}. 該值應小於 {{ compared_value }} 。 This value should be less than or equal to {{ compared_value }}. 該值應小於或等於 {{ compared_value }} 。 This value should not be equal to {{ compared_value }}. 該值應不等於 {{ compared_value }} 。 This value should not be identical to {{ compared_value_type }} {{ compared_value }}. 該值不應與 {{ compared_value_type }} {{ compared_value }} 相同。 PK]@T'%BB2Validator/Resources/translations/validators.vi.xlfnu[ This value should be false. Giá trị này phải là sai. This value should be true. Giá trị này phải là đúng. This value should be of type {{ type }}. Giá trị này phải là kiểu {{ type }}. This value should be blank. Giá trị này phải rỗng. The value you selected is not a valid choice. Giá trị bạn vừa chọn không hợp lệ. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Bạn phải chọn ít nhất {{ limit }} lựa chọn.|Bạn phải chọn ít nhất {{ limit }} lựa chọn. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Bạn phải chọn nhiều nhất {{ limit }} lựa chọn.|Bạn phải chọn nhiều nhất {{ limit }} lựa chọn. One or more of the given values is invalid. Một hoặc nhiều giá trị được chọn không hợp lệ. The fields {{ fields }} were not expected. Trường có tên {{ fields }} không được chấp nhận. The fields {{ fields }} are missing. Trường có tên {{ fields }} không tìm thấy. This value is not a valid date. Giá trị không phải là ngày hợp lệ. This value is not a valid datetime. Giá trị không phải là ngày tháng hợp lệ. This value is not a valid email address. Giá trị này không phải là email hợp lệ. The file could not be found. Tập tin không tìm thấy. The file is not readable. Tập tin không thể đọc được. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Tập tin quá lớn ({{ size }} {{ suffix }}). Kích thước tối đa cho phép {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Kiểu mime của tập tin không hợp lệ ({{ type }}). Kiểu hợp lệ là {{ types }}. This value should be {{ limit }} or less. Giá trị phải bằng hoặc nhỏ hơn {{ limit }}. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Giá trị quá dài. Phải bằng hoặc ít hơn {{ limit }} kí tự.|Giá trị quá dài. Phải bằng hoặc ít hơn {{ limit }} kí tự. This value should be {{ limit }} or more. Giá trị phải lớn hơn hoặc bằng {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Giá trị quá ngắn. Phải hơn hoặc bằng {{ limit }} kí tự.|Giá trị quá ngắn. Phải hơn hoặc bằng {{ limit }} kí tự. This value should not be blank. Giá trị không được phép để trống. This value should not be null. Giá trị không được phép rỗng. This value should be null. Giá trị phải rỗng. This value is not valid. Giá trị không hợp lệ. This value is not a valid time. Giá trị không phải là thời gian hợp lệ. This value is not a valid URL. Giá trị không phải là địa chỉ URL hợp lệ. The two values should be equal. Hai giá trị phải bằng nhau. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Tập tin quá lớn. Kích thước tối đa cho phép là {{ limit }} {{ suffix }}. The file is too large. Tập tin quá lớn. The file could not be uploaded. Tập tin không thể tải lên. This value should be a valid number. Giá trị phải là con số. This file is not a valid image. Tập tin không phải là hình ảnh. This is not a valid IP address. Địa chỉ IP không hợp lệ. This value is not a valid language. Giá trị không phải là ngôn ngữ hợp lệ. This value is not a valid locale. Giá trị không phải là một bản địa địa phương hợp lệ. This value is not a valid country. Giá trị không phải là nước hợp lệ. This value is already used. Giá trị đã được sử dụng. The size of the image could not be detected. Kích thước của hình ảnh không thể xác định. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Chiều rộng của hình quá lớn ({{ width }}px). Chiều rộng tối đa phải là {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Chiều rộng của hình quá thấp ({{ width }}px). Chiều rộng tối thiểu phải là {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Chiều cao của hình quá cao ({{ height }}px). Chiều cao tối đa phải là {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Chiều cao của hình quá thấp ({{ height }}px). Chiều cao tối thiểu phải là {{ min_height }}px. This value should be the user current password. Giá trị này phải là mật khẩu hiện tại của người dùng. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Giá trị phải có chính xác {{ limit }} kí tự.|Giá trị phải có chính xác {{ limit }} kí tự. The file was only partially uploaded. Tập tin chỉ được tải lên một phần. No file was uploaded. Tập tin không được tải lên. No temporary folder was configured in php.ini. Thư mục tạm không được định nghĩa trong php.ini. Cannot write temporary file to disk. Không thể ghi tập tin tạm ra đĩa. A PHP extension caused the upload to fail. Một PHP extension đã phá hỏng quá trình tải lên của tập tin. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Danh sách phải chứa chính xác {{ limit }} thành phần.|Danh sách phải chứa chính xác {{ limit }} thành phần. Invalid card number. Số thẻ không hợp lệ. Unsupported card type or invalid card number. Thẻ không được hỗ trợ hoặc số thẻ không hợp lệ. This is not a valid International Bank Account Number (IBAN). Giá trị không phải là International Bank Account Number (IBAN) hợp lệ. This value is not a valid ISBN-10. Giá trị không phải là ISBN-10 hợp lệ. This value is not a valid ISBN-13. Giá trị không phải là ISBN-13 hợp lệ. This value is neither a valid ISBN-10 nor a valid ISBN-13. Giá trị không phải là ISBN-10 hoặc ISBN-13 hợp lệ. This value is not a valid ISSN. Giá trị không là ISSN hợp lệ. This value is not a valid currency. Giá trị không phải là đơn vi tiền tệ hợp lệ. This value should be equal to {{ compared_value }}. Giá trị phải bằng {{ compared_value }}. This value should be greater than {{ compared_value }}. Giá trị phải lớn hơn {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Giá trị phải lớn hơn hoặc bằng {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Giá trị phải giống {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Giá trị phải bé hơn {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Giá trị không được phép nhỏ hơn hoặc bằng {{ compared_value }}. This value should not be equal to {{ compared_value }}. Giá trị không được phép bằng {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Giá trị không được phép giống như {{ compared_value_type }} {{ compared_value }}. PK]e]߭AA7Validator/Resources/translations/validators.sr_Cyrl.xlfnu[ This value should be false. Вредност треба да буде нетачна. This value should be true. Вредност треба да буде тачна. This value should be of type {{ type }}. Вредност треба да буде типа {{ type }}. This value should be blank. Вредност треба да буде празна. The value you selected is not a valid choice. Вредност треба да буде једна од понуђених. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Изаберите бар {{ limit }} могућност.|Изаберите бар {{ limit }} могућности.|Изаберите бар {{ limit }} могућности. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Изаберите највише {{ limit }} могућност.|Изаберите највише {{ limit }} могућности.|Изаберите највише {{ limit }} могућности. One or more of the given values is invalid. Једна или више вредности је невалидна. The fields {{ fields }} were not expected. Поља {{ fields }} нису била очекивана. The fields {{ fields }} are missing. Поља {{ fields }} недостају. This value is not a valid date. Вредност није валидан датум. This value is not a valid datetime. Вредност није валидан датум-време. This value is not a valid email address. Вредност није валидна адреса електронске поште. The file could not be found. Датотека не може бити пронађена. The file is not readable. Датотека није читљива. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Датотека је превелика ({{ size }} {{ suffix }}). Највећа дозвољена величина је {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Миме тип датотеке није валидан ({{ type }}). Дозвољени миме типови су {{ types }}. This value should be {{ limit }} or less. Вредност треба да буде {{ limit }} или мање. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Вредност је предугачка. Треба да има {{ limit }} карактер или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање. This value should be {{ limit }} or more. Вредност треба да буде {{ limit }} или више. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Вредност је прекратка. Треба да има {{ limit }} карактер или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више. This value should not be blank. Вредност не треба да буде празна. This value should not be null. Вредност не треба да буде null. This value should be null. Вредност треба да буде null. This value is not valid. Вредност је невалидна. This value is not a valid time. Вредност није валидно време. This value is not a valid URL. Вредност није валидан URL. The two values should be equal. Обе вредности треба да буду једнаке. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Датотека је превелика. Највећа дозвољена величина је {{ limit }} {{ suffix }}. The file is too large. Датотека је превелика. The file could not be uploaded. Датотека не може бити отпремљена. This value should be a valid number. Вредност треба да буде валидан број. This file is not a valid image. Ова датотека није валидна слика. This is not a valid IP address. Ово није валидна ИП адреса. This value is not a valid language. Вредност није валидан језик. This value is not a valid locale. Вредност није валидан локал. This value is not a valid country. Вредност није валидна земља. This value is already used. Вредност је већ искоришћена. The size of the image could not be detected. Величина слике не може бити одређена. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Ширина слике је превелика ({{ width }}px). Најећа дозвољена ширина је {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Ширина слике је премала ({{ width }}px). Најмања дозвољена ширина је {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Висина слике је превелика ({{ height }}px). Најећа дозвољена висина је {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Висина слике је премала ({{ height }}px). Најмања дозвољена висина је {{ min_height }}px. This value should be the user current password. Вредност треба да буде тренутна корисничка лозинка. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Вредност треба да има тачно {{ limit }} карактер.|Вредност треба да има тачно {{ limit }} карактера.|Вредност треба да има тачно {{ limit }} карактера. The file was only partially uploaded. Датотека је само парцијално отпремљена. No file was uploaded. Датотека није отпремљена. No temporary folder was configured in php.ini. Привремени директоријум није конфигурисан у php.ini. Cannot write temporary file to disk. Немогуће писање привремене датотеке на диск. A PHP extension caused the upload to fail. PHP екстензија је проузроковала неуспех отпремања датотеке. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ова колекција треба да садржи тачно {{ limit }} елемент.|Ова колекција треба да садржи тачно {{ limit }} елемента.|Ова колекција треба да садржи тачно {{ limit }} елемената. Invalid card number. Невалидан број картице. Unsupported card type or invalid card number. Невалидан број картице или тип картице није подржан. This is not a valid International Bank Account Number (IBAN). Ово није валидан међународни број банковног рачуна (IBAN). This value is not a valid ISBN-10. Ово није валидан ISBN-10. This value is not a valid ISBN-13. Ово није валидан ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ово није валидан ISBN-10 или ISBN-13. This value is not a valid ISSN. Ово није валидан ISSN. PK]AA2Validator/Resources/translations/validators.ja.xlfnu[ This value should be false. falseでなければなりません。 This value should be true. trueでなければなりません。 This value should be of type {{ type }}. 型は{{ type }}でなければなりません。 This value should be blank. 空でなければなりません。 The value you selected is not a valid choice. 有効な選択肢ではありません。 You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. {{ limit }}個以上選択してください。 You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. {{ limit }}個以内で選択してください。 One or more of the given values is invalid. 無効な選択肢が含まれています。 The fields {{ fields }} were not expected. フィールド{{ fields }}は無効です。 The fields {{ fields }} are missing. フィールド{{ fields }}は必須です。 This value is not a valid date. 有効な日付ではありません。 This value is not a valid datetime. 有効な日時ではありません。 This value is not a valid email address. 有効なメールアドレスではありません。 The file could not be found. ファイルが見つかりません。 The file is not readable. ファイルを読み込めません。 The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. ファイルのサイズが大きすぎます({{ size }} {{ suffix }})。有効な最大サイズは{{ limit }} {{ suffix }}です。 The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. ファイルのMIMEタイプが無効です({{ type }})。有効なMIMEタイプは{{ types }}です。 This value should be {{ limit }} or less. {{ limit }}以下でなければなりません。 This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. 値が長すぎます。{{ limit }}文字以内でなければなりません。 This value should be {{ limit }} or more. {{ limit }}以上でなければなりません。 This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. 値が短すぎます。{{ limit }}文字以上でなければなりません。 This value should not be blank. 空であってはなりません。 This value should not be null. nullであってはなりません。 This value should be null. nullでなければなりません。 This value is not valid. 有効な値ではありません。 This value is not a valid time. 有効な時刻ではありません。 This value is not a valid URL. 有効なURLではありません。 The two values should be equal. 2つの値が同じでなければなりません。 The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. ファイルのサイズが大きすぎます。有効な最大サイズは{{ limit }} {{ suffix }}です。 The file is too large. ファイルのサイズが大きすぎます。 The file could not be uploaded. ファイルをアップロードできませんでした。 This value should be a valid number. 有効な数字ではありません。 This file is not a valid image. ファイルが画像ではありません。 This is not a valid IP address. 有効なIPアドレスではありません。 This value is not a valid language. 有効な言語名ではありません。 This value is not a valid locale. 有効なロケールではありません。 This value is not a valid country. 有効な国名ではありません。 This value is already used. 既に使用されています。 The size of the image could not be detected. 画像のサイズが検出できません。 The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. 画像の幅が大きすぎます({{ width }}ピクセル)。{{ max_width }}ピクセルまでにしてください。 The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. 画像の幅が小さすぎます({{ width }}ピクセル)。{{ min_width }}ピクセル以上にしてください。 The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. 画像の高さが大きすぎます({{ height }}ピクセル)。{{ max_height }}ピクセルまでにしてください。 The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. 画像の高さが小さすぎます({{ height }}ピクセル)。{{ min_height }}ピクセル以上にしてください。 This value should be the user current password. ユーザーの現在のパスワードでなければなりません。 This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. ちょうど{{ limit }}文字でなければなりません。 The file was only partially uploaded. ファイルのアップロードは完全ではありません。 No file was uploaded. ファイルがアップロードされていません。 No temporary folder was configured in php.ini. php.iniで一時フォルダが設定されていません。 Cannot write temporary file to disk. 一時ファイルをディスクに書き込むことができません。 A PHP extension caused the upload to fail. PHP拡張によってアップロードに失敗しました。 This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. {{ limit }}個以上の要素を含んでなければいけません。 This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. 要素は{{ limit }}個までです。 This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. 要素はちょうど{{ limit }}個でなければなりません。 Invalid card number. 無効なカード番号です。 Unsupported card type or invalid card number. 未対応のカード種類又は無効なカード番号です。 This is not a valid International Bank Account Number (IBAN). 有効なIBANコードではありません。 This value is not a valid ISBN-10. 有効なISBN-10コードではありません。 This value is not a valid ISBN-13. 有効なISBN-13コードではありません。 This value is neither a valid ISBN-10 nor a valid ISBN-13. 有効なISBN-10コード又はISBN-13コードではありません。 This value is not a valid ISSN. 有効なISSNコードではありません。 This value is not a valid currency. 有効な貨幣ではありません。 This value should be equal to {{ compared_value }}. {{ compared_value }}と等しくなければなりません。 This value should be greater than {{ compared_value }}. {{ compared_value }}より大きくなければなりません。 This value should be greater than or equal to {{ compared_value }}. {{ compared_value }}以上でなければなりません。 This value should be identical to {{ compared_value_type }} {{ compared_value }}. {{ compared_value_type }}としての{{ compared_value }}と等しくなければなりません。 This value should be less than {{ compared_value }}. {{ compared_value }}未満でなければなりません。 This value should be less than or equal to {{ compared_value }}. {{ compared_value }}以下でなければなりません。 This value should not be equal to {{ compared_value }}. {{ compared_value }}と等しくてはいけません。 This value should not be identical to {{ compared_value_type }} {{ compared_value }}. {{ compared_value_type }}としての{{ compared_value }}と等しくてはいけません。 PK]-112Validator/Resources/translations/validators.cy.xlfnu[ This value should be false. Dylid bod y gwerth hwn yn ffug. This value should be true. Dylid bod y gwerth hwn yn wir. This value should be of type {{ type }}. Dylid bod y gwerth hwn bod o fath {{ type }}. This value should be blank. Dylid bod y gwerth hwn yn wag. The value you selected is not a valid choice. Nid yw'r gwerth â ddewiswyd yn ddilys. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Rhaid dewis o leiaf {{ limit }} opsiwn. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Rhaid dewis dim mwy na {{ limit }} opsiwn. One or more of the given values is invalid. Mae un neu fwy o'r gwerthoedd a roddwyd yn annilys. The fields {{ fields }} were not expected. Roedd y maesydd {{ fields }} yn anisgwyl. The fields {{ fields }} are missing. Roedd y maesydd {{ fields }} ar goll. This value is not a valid date. Nid yw'r gwerth yn ddyddiad dilys. This value is not a valid datetime. Nid yw'r gwerth yn datetime dilys. This value is not a valid email address. Nid yw'r gwerth yn gyfeiriad ebost dilys. The file could not be found. Ni ddarganfyddwyd y ffeil. The file is not readable. Ni ellir darllen y ffeil. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Mae'r ffeil yn rhy fawr ({{ size }} {{ suffix }}). Yr uchafswm â ganiateir yw {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Nid yw math mime y ffeil yn ddilys ({{ type }}). Dyma'r mathau â ganiateir {{ types }}. This value should be {{ limit }} or less. Dylai'r gwerth hwn fod yn {{ limit }} neu lai. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Mae'r gwerth hwn rhy hir. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu lai. This value should be {{ limit }} or more. Dylai'r gwerth hwn fod yn {{ limit }} neu fwy. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Mae'r gwerth hwn yn rhy fyr. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu fwy. This value should not be blank. Ni ddylai'r gwerth hwn fod yn wag. This value should not be null. Ni ddylai'r gwerth hwn fod yn null. This value should be null. Dylai'r gwerth fod yn null. This value is not valid. Nid yw'r gwerth hwn yn ddilys. This value is not a valid time. Nid yw'r gwerth hwn yn amser dilys. This value is not a valid URL. Nid yw'r gwerth hwn yn URL dilys. The two values should be equal. Rhaid i'r ddau werth fod yn gyfystyr a'u gilydd. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Mae'r ffeil yn rhy fawr. Yr uchafswm â ganiateir yw {{ limit }} {{ suffix }}. The file is too large. Mae'r ffeil yn rhy fawr. The file could not be uploaded. Methwyd ag uwchlwytho'r ffeil. This value should be a valid number. Dylai'r gwerth hwn fod yn rif dilys. This file is not a valid image. Nid yw'r ffeil hon yn ddelwedd dilys. This is not a valid IP address. Nid yw hwn yn gyfeiriad IP dilys. This value is not a valid language. Nid yw'r gwerth hwn yn iaith ddilys. This value is not a valid locale. Nid yw'r gwerth hwn yn locale dilys. This value is not a valid country. Nid yw'r gwerth hwn yn wlad dilys. This value is already used. Mae'r gwerth hwn eisoes yn cael ei ddefnyddio. The size of the image could not be detected. Methwyd â darganfod maint y ddelwedd. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Mae lled y ddelwedd yn rhy fawr ({{ width }}px). Y lled mwyaf â ganiateir yw {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Mae lled y ddelwedd yn rhy fach ({{ width }}px). Y lled lleiaf â ganiateir yw {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Mae uchder y ddelwedd yn rhy fawr ({{ width }}px). Yr uchder mwyaf â ganiateir yw {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Mae uchder y ddelwedd yn rhy fach ({{ width }}px). Yr uchder lleiaf â ganiateir yw {{ min_height }}px. This value should be the user current password. Dylaid bod y gwerth hwn yn gyfrinair presenol y defnyddiwr. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Dylai'r gwerth hwn fod yn union {{ limit }} nodyn cyfrifiadurol o hyd. The file was only partially uploaded. Dim ond rhan o'r ffeil ag uwchlwythwyd. No file was uploaded. Ni uwchlwythwyd unrhyw ffeil. No temporary folder was configured in php.ini. Nid oes ffolder dros-dro wedi'i gosod yn php.ini. Cannot write temporary file to disk. Methwyd ag ysgrifennu'r ffeil dros-dro ar ddisg. A PHP extension caused the upload to fail. Methwyd ag uwchlwytho oherwydd ategyn PHP. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu fwy. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu lai. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Dylai'r casgliad hwn gynnwys union {{ limit }} elfen. Invalid card number. Nid oedd rhif y cerdyn yn ddilys. Unsupported card type or invalid card number. Unai ni dderbynir y math yna o gerdyn, neu nid yw rhif y cerdyn yn ddilys. PK]OO2Validator/Resources/translations/validators.ar.xlfnu[ This value should be false. هذه القيمة يجب أن تكون خاطئة. This value should be true. هذه القيمة يجب أن تكون حقيقية. This value should be of type {{ type }}. هذه القيمة يجب ان تكون من نوع {{ type }}. This value should be blank. هذه القيمة يجب ان تكون فارغة. The value you selected is not a valid choice. القيمة المختارة ليست خيارا صحيحا. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيارات على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيارات على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر. One or more of the given values is invalid. واحد أو أكثر من القيم المعطاه خاطئ. The fields {{ fields }} were not expected. القيم {{ fields }} لم تكن متوقعة. The fields {{ fields }} are missing. القيم {{ fields }} مفقودة. This value is not a valid date. هذه القيمة ليست تاريخا صالحا. This value is not a valid datetime. هذه القيمة ليست تاريخا و وقتا صالحا. This value is not a valid email address. هذه القيمة ليست عنوان بريد إلكتروني صحيح. The file could not be found. لا يمكن العثور على الملف. The file is not readable. الملف غير قابل للقراءة. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. الملف كبير جدا ({{ size }} {{ suffix }}).اقصى مساحه مسموح بها ({{ limit }} {{ suffix }}). The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. نوع الملف غير صحيح ({{ type }}). الانواع المسموح بها هى {{ types }}. This value should be {{ limit }} or less. هذه القيمة يجب ان تكون {{ limit }} او اقل. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حروف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل. This value should be {{ limit }} or more. هذه القيمة يجب ان تكون {{ limit }} او اكثر. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حروف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر. This value should not be blank. هذه القيمة يجب الا تكون فارغة. This value should not be null. هذه القيمة يجب الا تكون فارغة. This value should be null. هذه القيمة يجب ان تكون فارغة. This value is not valid. هذه القيمة غير صحيحة. This value is not a valid time. هذه القيمة ليست وقت صحيح. This value is not a valid URL. هذه القيمة ليست رابط الكترونى صحيح. The two values should be equal. القيمتان يجب ان تكونا متساويتان. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. الملف كبير جدا. اقصى مساحه مسموح بها {{ limit }} {{ suffix }}. The file is too large. الملف كبير جدا. The file could not be uploaded. لم استطع استقبال الملف. This value should be a valid number. هذه القيمة يجب ان تكون رقم. This file is not a valid image. هذا الملف ليس صورة صحيحة. This is not a valid IP address. هذه القيمة ليست عنوان رقمى صحيح. This value is not a valid language. هذه القيمة ليست لغة صحيحة. This value is not a valid locale. هذه القيمة ليست موقع صحيح. This value is not a valid country. هذه القيمة ليست بلدا صالحا. This value is already used. هذه القيمة مستخدمة بالفعل. The size of the image could not be detected. لم استطع معرفة حجم الصورة. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. عرض الصورة كبير جدا ({{ width }}px). اقصى عرض مسموح به هو{{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. عرض الصورة صغير جدا ({{ width }}px). اقل عرض مسموح به هو{{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. طول الصورة كبير جدا ({{ height }}px). اقصى طول مسموح به هو{{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. طول الصورة صغير جدا ({{ height }}px). اقل طول مسموح به هو{{ min_height }}px. This value should be the user current password. هذه القيمة يجب ان تكون كلمة سر المستخدم الحالية. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حروف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط. The file was only partially uploaded. تم استقبال جزء من الملف فقط. No file was uploaded. لم يتم ارسال اى ملف. No temporary folder was configured in php.ini. لم يتم تهيئة حافظة مؤقتة فى ملف php.ini. Cannot write temporary file to disk. لم استطع كتابة الملف المؤقت. A PHP extension caused the upload to fail. احد اضافات PHP تسببت فى فشل استقبال الملف. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط. Invalid card number. رقم البطاقه غير صحيح. Unsupported card type or invalid card number. نوع البطاقه غير مدعوم او الرقم غير صحيح. This is not a valid International Bank Account Number (IBAN). الرقم IBAN (رقم الحساب المصرفي الدولي) الذي تم إدخاله غير صالح. This value is not a valid ISBN-10. هذه القيمة ليست ISBN-10 صالحة. This value is not a valid ISBN-13. هذه القيمة ليست ISBN-13 صالحة. This value is neither a valid ISBN-10 nor a valid ISBN-13. هذه القيمة ليست ISBN-10 صالحة ولا ISBN-13 صالحة. This value is not a valid ISSN. هذه القيمة ليست ISSN صالحة. This value is not a valid currency. العُملة غير صحيحة. This value should be equal to {{ compared_value }}. القيمة يجب ان تساوي {{ compared_value }}. This value should be greater than {{ compared_value }}. القيمة يجب ان تكون اعلي من {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. القيمة يجب ان تكون مساوية او اعلي من {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. القيمة يجب ان تطابق {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. القيمة يجب ان تكون اقل من {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. القيمة يجب ان تساوي او تقل عن {{ compared_value }}. This value should not be equal to {{ compared_value }}. القيمة يجب ان لا تساوي {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. القيمة يجب ان لا تطابق {{ compared_value_type }} {{ compared_value }}. PK]qb??2Validator/Resources/translations/validators.lb.xlfnu[ This value should be false. Dëse Wäert sollt falsch sinn. This value should be true. Dëse Wäert sollt wouer sinn. This value should be of type {{ type }}. Dëse Wäert sollt vum Typ {{ type }} sinn. This value should be blank. Dëse Wäert sollt eidel sinn. The value you selected is not a valid choice. Dëse Wäert sollt enger vun de Wielméiglechkeeten entspriechen. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Dir sollt mindestens {{ limit }} Méiglechkeete wielen. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Dir sollt héchstens {{ limit }} Méiglechkeete wielen. One or more of the given values is invalid. Een oder méi vun de Wäerter ass ongëlteg. The fields {{ fields }} were not expected. D'Felder {{ fields }} goufen net erwaart. The fields {{ fields }} are missing. D'Felder {{ fields }} feelen. This value is not a valid date. Dëse Wäert entsprécht kenger gëlteger Datumsangab. This value is not a valid datetime. Dëse Wäert entsprécht kenger gëlteger Datums- an Zäitangab. This value is not a valid email address. Dëse Wäert ass keng gëlteg Email-Adress. The file could not be found. De Fichier gouf net fonnt. The file is not readable. De Fichier ass net liesbar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. De Fichier ass ze grouss ({{ size }} {{ suffix }}). Déi zougeloosse Maximalgréisst bedréit {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Den Typ vum Fichier ass ongëlteg ({{ type }}). Erlaabten Type sinn {{ types }}. This value should be {{ limit }} or less. Dëse Wäert soll méi kleng oder gläich {{ limit }} sinn. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Dës Zeecheketten ass ze laang. Se sollt héchstens {{ limit }} Zeechen hunn. This value should be {{ limit }} or more. Dëse Wäert sollt méi grouss oder gläich {{ limit }} sinn. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Dës Zeecheketten ass ze kuerz. Se sollt mindestens {{ limit }} Zeechen hunn. This value should not be blank. Dëse Wäert sollt net eidel sinn. This value should not be null. Dëst sollt keen Null-Wäert sinn. This value should be null. Dëst sollt keen Null-Wäert sinn. This value is not valid. Dëse Wäert ass net gëlteg. This value is not a valid time. Dëse Wäert entsprécht kenger gëlteger Zäitangab. This value is not a valid URL. Dëse Wäert ass keng gëlteg URL. The two values should be equal. Béid Wäerter sollten identesch sinn. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. De fichier ass ze grouss. Déi maximal Gréisst dierf {{ limit }} {{ suffix }} net depasséieren. The file is too large. De Fichier ass ze grouss. The file could not be uploaded. De Fichier konnt net eropgeluede ginn. This value should be a valid number. Dëse Wäert sollt eng gëlteg Zuel sinn. This file is not a valid image. Dëse Fichier ass kee gëltegt Bild. This is not a valid IP address. Dëst ass keng gëlteg IP-Adress. This value is not a valid language. Dëse Wäert aentsprécht kenger gëlteger Sprooch. This value is not a valid locale. Dëse Wäert entsprécht kengem gëltege Gebittsschema. This value is not a valid country. Dëse Wäert entsprécht kengem gëltege Land. This value is already used. Dëse Wäert gëtt scho benotzt. The size of the image could not be detected. D'Gréisst vum Bild konnt net detektéiert ginn. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. D'Breet vum Bild ass ze grouss ({{ width }}px). Déi erlaabte maximal Breet ass {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. D'Breet vum Bild ass ze kleng ({{ width }}px). Déi minimal Breet ass {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. D'Héicht vum Bild ass ze grouss ({{ height }}px). Déi erlaabte maximal Héicht ass {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. D'Héicht vum Bild ass ze kleng ({{ height }}px). Déi minimal Héicht ass {{ min_height }}px. This value should be the user current password. Dëse Wäert sollt dem aktuelle Benotzerpasswuert entspriechen. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Dëse Wäert sollt exactly {{ limit }} Buschtaf hunn.|Dëse Wäert sollt exakt {{ limit }} Buschtawen hunn. The file was only partially uploaded. De Fichier gouf just deelweis eropgelueden. No file was uploaded. Et gouf kee Fichier eropgelueden. No temporary folder was configured in php.ini. Et gouf keen temporären Dossier an der php.ini konfiguréiert. Cannot write temporary file to disk. Den temporäre Fichier kann net gespäichert ginn. A PHP extension caused the upload to fail. Eng PHP-Erweiderung huet den Upload verhënnert. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Dës Sammlung sollt {{ limit }} oder méi Elementer hunn. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Dës Sammlung sollt {{ limit }} oder manner Elementer hunn. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Dës Sammlung sollt exakt {{ limit }} Element hunn.|Dës Sammlung sollt exakt {{ limit }} Elementer hunn. Invalid card number. Ongëlteg Kaartennummer. Unsupported card type or invalid card number. Net ënnerstëtzte Kaartentyp oder ongëlteg Kaartennummer. This is not a valid International Bank Account Number (IBAN). Dëst ass keng gëlteg IBAN-Kontonummer. This value is not a valid ISBN-10. Dëse Wäert ass keng gëlteg ISBN-10. This value is not a valid ISBN-13. Dëse Wäert ass keng gëlteg ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Dëse Wäert ass weder eng gëlteg ISBN-10 nach eng gëlteg ISBN-13. This value is not a valid ISSN. Dëse Wäert ass keng gëlteg ISSN. This value is not a valid currency. Dëse Wäert ass keng gëlteg Währung. This value should be equal to {{ compared_value }}. Dëse Wäert sollt {{ compared_value }} sinn. This value should be greater than {{ compared_value }}. Dëse Wäert sollt méi grouss wéi {{ compared_value }} sinn. This value should be greater than or equal to {{ compared_value }}. Dëse Wäert sollt méi grouss wéi oder gläich {{ compared_value }} sinn. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Dëse Wäert sollt identesch si mat {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Dëse Wäert sollt méi kleng wéi {{ compared_value }} sinn. This value should be less than or equal to {{ compared_value }}. Dëse Wäert sollt méi kleng wéi oder gläich {{ compared_value }} sinn. This value should not be equal to {{ compared_value }}. Dëse Wäert sollt net {{ compared_value }} sinn. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Dëse Wäert sollt net identesch si mat {{ compared_value_type }} {{ compared_value }}. PK]"}2A2A2Validator/Resources/translations/validators.es.xlfnu[ This value should be false. Este valor debería ser falso. This value should be true. Este valor debería ser verdadero. This value should be of type {{ type }}. Este valor debería ser de tipo {{ type }}. This value should be blank. Este valor debería estar vacío. The value you selected is not a valid choice. El valor seleccionado no es una opción válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Debe seleccionar al menos {{ limit }} opción.|Debe seleccionar al menos {{ limit }} opciones. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opciones. One or more of the given values is invalid. Uno o más de los valores indicados no son válidos. The fields {{ fields }} were not expected. No se esperaban los campos {{ fields }}. The fields {{ fields }} are missing. Faltan los campos {{ fields }}. This value is not a valid date. Este valor no es una fecha válida. This value is not a valid datetime. Este valor no es una fecha y hora válidas. This value is not a valid email address. Este valor no es una dirección de email válida. The file could not be found. No se pudo encontrar el archivo. The file is not readable. No se puede leer el archivo. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. El archivo es demasiado grande ({{ size }} {{ suffix }}). El tamaño máximo permitido es {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. El tipo mime del archivo no es válido ({{ type }}). Los tipos mime válidos son {{ types }}. This value should be {{ limit }} or less. Este valor debería ser {{ limit }} o menos. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Este valor es demasiado largo. Debería tener {{ limit }} carácter o menos.|Este valor es demasiado largo. Debería tener {{ limit }} caracteres o menos. This value should be {{ limit }} or more. Este valor debería ser {{ limit }} o más. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Este valor es demasiado corto. Debería tener {{ limit }} carácter o más.|Este valor es demasiado corto. Debería tener {{ limit }} caracteres o más. This value should not be blank. Este valor no debería estar vacío. This value should not be null. Este valor no debería ser nulo. This value should be null. Este valor debería ser nulo. This value is not valid. Este valor no es válido. This value is not a valid time. Este valor no es una hora válida. This value is not a valid URL. Este valor no es una URL válida. The two values should be equal. Los dos valores deberían ser iguales. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. El archivo es demasiado grande. El tamaño máximo permitido es {{ limit }} {{ suffix }}. The file is too large. El archivo es demasiado grande. The file could not be uploaded. No se pudo subir el archivo. This value should be a valid number. Este valor debería ser un número válido. This file is not a valid image. El archivo no es una imagen válida. This is not a valid IP address. Esto no es una dirección IP válida. This value is not a valid language. Este valor no es un idioma válido. This value is not a valid locale. Este valor no es una localización válida. This value is not a valid country. Este valor no es un país válido. This value is already used. Este valor ya se ha utilizado. The size of the image could not be detected. No se pudo determinar el tamaño de la imagen. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. La anchura de la imagen es demasiado grande ({{ width }}px). La anchura máxima permitida son {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. La anchura de la imagen es demasiado pequeña ({{ width }}px). La anchura mínima requerida son {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. La altura de la imagen es demasiado grande ({{ height }}px). La altura máxima permitida son {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. La altura de la imagen es demasiado pequeña ({{ height }}px). La altura mínima requerida son {{ min_height }}px. This value should be the user current password. Este valor debería ser la contraseña actual del usuario. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor debería tener exactamente {{ limit }} carácter.|Este valor debería tener exactamente {{ limit }} caracteres. The file was only partially uploaded. El archivo fue sólo subido parcialmente. No file was uploaded. Ningún archivo fue subido. No temporary folder was configured in php.ini. Ninguna carpeta temporal fue configurada en php.ini. Cannot write temporary file to disk. No se pudo escribir el archivo temporal en el disco. A PHP extension caused the upload to fail. Una extensión de PHP hizo que la subida fallara. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta colección debe contener {{ limit }} elemento o más.|Esta colección debe contener {{ limit }} elementos o más. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta colección debe contener {{ limit }} elemento o menos.|Esta colección debe contener {{ limit }} elementos o menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta colección debe contener exactamente {{ limit }} elemento.|Esta colección debe contener exactamente {{ limit }} elementos. Invalid card number. Número de tarjeta inválido. Unsupported card type or invalid card number. Tipo de tarjeta no soportado o número de tarjeta inválido. This is not a valid International Bank Account Number (IBAN). Esto no es un International Bank Account Number (IBAN) válido. This value is not a valid ISBN-10. Este valor no es un ISBN-10 válido. This value is not a valid ISBN-13. Este valor no es un ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor no es ni un ISBN-10 válido ni un ISBN-13 válido. This value is not a valid ISSN. Este valor no es un ISSN válido. This value is not a valid currency. Este valor no es una divisa válida. This value should be equal to {{ compared_value }}. Este valor debería ser igual que {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor debería ser mayor que {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor debería ser mayor o igual que {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor debería ser idéntico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor debería ser menor que {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor debería ser menor o igual que {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor debería ser distinto de {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor no debería ser idéntico a {{ compared_value_type }} {{ compared_value }}. PK]AA2Validator/Resources/translations/validators.ro.xlfnu[ This value should be false. Această valoare ar trebui să fie falsă (false). This value should be true. Această valoare ar trebui să fie adevărată (true). This value should be of type {{ type }}. Această valoare ar trebui să fie de tipul {{ type }}. This value should be blank. Această valoare ar trebui sa fie goală. The value you selected is not a valid choice. Valoarea selectată nu este o opțiune validă. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Trebuie să selectați cel puțin {{ limit }} opțiuni. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Trebuie să selectați cel mult {{ limit }} opțiuni. One or more of the given values is invalid. Una sau mai multe dintre valorile furnizate sunt invalide. The fields {{ fields }} were not expected. Câmpurile {{ fields }} nu erau așteptate. The fields {{ fields }} are missing. Câmpurile {{ fields }} lipsesc. This value is not a valid date. Această valoare nu reprezintă o dată validă. This value is not a valid datetime. Această valoare nu reprezintă o dată și oră validă. This value is not a valid email address. Această valoare nu reprezintă o adresă de e-mail validă. The file could not be found. Fișierul nu a putut fi găsit. The file is not readable. Fișierul nu poate fi citit. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fișierul este prea mare ({{ size }} {{ suffix }}). Dimensiunea maximă permisă este {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Tipul fișierului este invalid ({{ type }}). Tipurile permise de fișiere sunt ({{ types }}). This value should be {{ limit }} or less. Această valoare ar trebui să fie cel mult {{ limit }}. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caracter.|Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caractere. This value should be {{ limit }} or more. Această valoare ar trebui să fie cel puțin {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caracter.|Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caractere. This value should not be blank. Această valoare nu ar trebui să fie goală. This value should not be null. Această valoare nu ar trebui să fie nulă (null). This value should be null. Această valoare ar trebui să fie nulă (null). This value is not valid. Această valoare nu este validă. This value is not a valid time. Această valoare nu reprezintă o oră validă. This value is not a valid URL. Această valoare nu reprezintă un URL (link) valid. The two values should be equal. Cele două valori ar trebui să fie egale. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fișierul este prea mare. Mărimea maximă permisă este {{ limit }} {{ suffix }}. The file is too large. Fișierul este prea mare. The file could not be uploaded. Fișierul nu a putut fi încărcat. This value should be a valid number. Această valoare nu reprezintă un număr valid. This file is not a valid image. Acest fișier nu este o imagine validă. This is not a valid IP address. Această valoare nu este o adresă IP validă. This value is not a valid language. Această valoare nu reprezintă o limbă corectă. This value is not a valid locale. Această valoare nu reprezintă un dialect (o limbă) corect. This value is not a valid country. Această valoare nu este o țară validă. This value is already used. Această valoare este folosită deja. The size of the image could not be detected. Mărimea imaginii nu a putut fi detectată. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Lățimea imaginii este prea mare ({{ width }}px). Lățimea maximă permisă este de {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Lățimea imaginii este prea mică ({{ width }}px). Lățimea minimă permisă este de {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Înălțimea imaginii este prea mare ({{ height }}px). Înălțimea maximă permisă este de {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Înălțimea imaginii este prea mică ({{ height }}px). Înălțimea minimă permisă este de {{ min_height }}px. This value should be the user current password. Această valoare trebuie să fie parola curentă a utilizatorului. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Această valoare trebuie să conțină exact {{ limit }} caracter.|Această valoare trebuie să conțină exact {{ limit }} caractere. The file was only partially uploaded. Fișierul a fost încărcat parțial. No file was uploaded. Nu a fost încărcat nici un fișier. No temporary folder was configured in php.ini. Nu este configurat nici un director temporar in php.ini. Cannot write temporary file to disk. Nu a fost posibilă scrierea fișierului temporar pe disk. A PHP extension caused the upload to fail. O extensie PHP a prevenit încărcarea cu succes a fișierului. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Această colecție trebuie să conțină cel puțin {{ limit }} elemente. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Această colecție trebuie să conțină cel mult {{ limit }} elemente. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Această colecție trebuie să conțină {{ limit }} elemente. Invalid card number. Numărul card invalid. Unsupported card type or invalid card number. Tipul sau numărul cardului nu sunt valide. This is not a valid International Bank Account Number (IBAN). Acesta nu este un cod IBAN (International Bank Account Number) valid. This value is not a valid ISBN-10. Această valoare nu este un cod ISBN-10 valid. This value is not a valid ISBN-13. Această valoare nu este un cod ISBN-13 valid. This value is neither a valid ISBN-10 nor a valid ISBN-13. Această valoare nu este un cod ISBN-10 sau ISBN-13 valid. This value is not a valid ISSN. Această valoare nu este un cod ISSN valid. This value is not a valid currency. Această valoare nu este o monedă validă. This value should be equal to {{ compared_value }}. Această valoare trebuie să fie egală cu {{ compared_value }}. This value should be greater than {{ compared_value }}. Această valoare trebuie să fie mai mare de {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Această valoare trebuie să fie mai mare sau egală cu {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Această valoare trebuie identică cu {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Această valoare trebuie să fie mai mică de {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Această valoare trebuie să fie mai mică sau egală cu {{ compared_value }}. This value should not be equal to {{ compared_value }}. Această valoare nu trebuie să fie egală cu {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Această valoare nu trebuie să fie identică cu {{ compared_value_type }} {{ compared_value }}. PK]τ}K}K2Validator/Resources/translations/validators.uk.xlfnu[ This value should be false. Значення повинно бути Ні. This value should be true. Значення повинно бути Так. This value should be of type {{ type }}. Тип значення повинен бути {{ type }}. This value should be blank. Значення повинно бути пустим. The value you selected is not a valid choice. Обране вами значення недопустиме. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Ви повинні обрати хоча б {{ limit }} варіант.|Ви повинні обрати хоча б {{ limit }} варіанти.|Ви повинні обрати хоча б {{ limit }} варіантів. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Ви повинні обрати не більше ніж {{ limit }} варіантів. One or more of the given values is invalid. Одне або кілька заданих значень є недопустимі. The fields {{ fields }} were not expected. Поля {{ fields }} не очікувалися. The fields {{ fields }} are missing. Поля {{ fields }} відсутні. This value is not a valid date. Дане значення не є вірною датою. This value is not a valid datetime. Дане значення дати та часу недопустиме. This value is not a valid email address. Значення адреси электронної пошти недопустиме. The file could not be found. Файл не знайдено. The file is not readable. Файл не читається. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файл занадто великий ({{ size }} {{ suffix }}). Дозволений максимальний розмір {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. MIME-тип файлу недопустимий ({{ type }}). Допустимі MIME-типи файлів {{ types }}. This value should be {{ limit }} or less. Значення повинно бути {{ limit }} або менше. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Значення занадто довге. Повинно бути рівне {{ limit }} символу або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше. This value should be {{ limit }} or more. Значення повинно бути {{ limit }} або більше. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Значення занадто коротке. Повинно бути рівне {{ limit }} символу або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше. This value should not be blank. Значення не повинно бути пустим. This value should not be null. Значення не повинно бути null. This value should be null. Значення повинно бути null. This value is not valid. Значення недопустиме. This value is not a valid time. Значення часу недопустиме. This value is not a valid URL. Значення URL недопустиме. The two values should be equal. Обидва занчення повинні бути одинаковими. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файл занадто великий. Максимальний допустимий розмір {{ limit }} {{ suffix }}. The file is too large. Файл занадто великий. The file could not be uploaded. Файл не можливо завантажити. This value should be a valid number. Значення має бути допустимим числом. This file is not a valid image. Цей файл не є допустимим форматом зображення. This is not a valid IP address. Це некоректна IP адреса. This value is not a valid language. Це некоректна мова. This value is not a valid locale. Це некоректна локалізація. This value is not a valid country. Це некоректна країна. This value is already used. Це значення вже використовується. The size of the image could not be detected. Не вдалося визначити розмір зображення. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Ширина зображення занадто велика ({{ width }}px). Максимально допустима ширина {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Ширина зображення занадто мала ({{ width }}px). Мінімально допустима ширина {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Висота зображення занадто велика ({{ height }}px). Максимально допустима висота {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Висота зображення занадто мала ({{ height }}px). Мінімально допустима висота {{ min_height }}px. This value should be the user current password. Значення має бути поточним паролем користувача. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Значення повиино бути рівним {{ limit }} символу.|Значення повиино бути рівним {{ limit }} символам.|Значення повиино бути рівним {{ limit }} символам. The file was only partially uploaded. Файл був завантажений лише частково. No file was uploaded. Файл не був завантажений. No temporary folder was configured in php.ini. Не налаштована тимчасова директорія в php.ini. Cannot write temporary file to disk. Неможливо записати тимчасовий файл на диск. A PHP extension caused the upload to fail. Розширення PHP викликало помилку при завантаженні. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ця колекція повинна містити {{ limit }} елемент чи більше.|Ця колекція повинна містити {{ limit }} елемента чи більше.|Ця колекція повинна містити {{ limit }} елементів чи більше. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ця колекція повинна містити {{ limit }} елемент чи менше.|Ця колекція повинна містити {{ limit }} елемента чи менше.|Ця колекція повинна містити {{ limit }} елементов чи менше. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ця колекція повинна містити рівно {{ limit }} елемент.|Ця колекція повинна містити рівно {{ limit }} елемента.|Ця колекція повинна містити рівно {{ limit }} елементів. Invalid card number. Невірний номер карти. Unsupported card type or invalid card number. Непідтримуваний тип карти або невірний номер карти. This is not a valid International Bank Account Number (IBAN). Це не дійсний міжнародний номер банківського рахунку (IBAN). This value is not a valid ISBN-10. Значення не у форматі ISBN-10. This value is not a valid ISBN-13. Значення не у форматі ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Значення не відповідає форматам ISBN-10 та ISBN-13. This value is not a valid ISSN. Значення має невірний формат ISSN. This value is not a valid currency. Значення має невірний формат валюти. This value should be equal to {{ compared_value }}. Значення повинно дорівнювати {{ compared_value }}. This value should be greater than {{ compared_value }}. Значення має бути більше ніж {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Значення має бути більше або дорівнювати {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Значення має бути ідентичним {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Значення повинно бути менше ніж {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Значення повинно бути менше або дорівнювати {{ compared_value }}. This value should not be equal to {{ compared_value }}. Значення не повинно дорівнювати {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Значення не повинно бути ідентичним {{ compared_value_type }} {{ compared_value }}. PK]+ B B2Validator/Resources/translations/validators.fr.xlfnu[ This value should be false. Cette valeur doit être fausse. This value should be true. Cette valeur doit être vraie. This value should be of type {{ type }}. Cette valeur doit être de type {{ type }}. This value should be blank. Cette valeur doit être vide. The value you selected is not a valid choice. Cette valeur doit être l'un des choix proposés. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Vous devez sélectionner au moins {{ limit }} choix.|Vous devez sélectionner au moins {{ limit }} choix. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Vous devez sélectionner au maximum {{ limit }} choix.|Vous devez sélectionner au maximum {{ limit }} choix. One or more of the given values is invalid. Une ou plusieurs des valeurs soumises sont invalides. The fields {{ fields }} were not expected. Les champs {{ fields }} n'ont pas été prévus. The fields {{ fields }} are missing. Les champs {{ fields }} sont manquants. This value is not a valid date. Cette valeur n'est pas une date valide. This value is not a valid datetime. Cette valeur n'est pas une date valide. This value is not a valid email address. Cette valeur n'est pas une adresse email valide. The file could not be found. Le fichier n'a pas été trouvé. The file is not readable. Le fichier n'est pas lisible. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Le fichier est trop volumineux ({{ size }} {{ suffix }}). Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Le type du fichier est invalide ({{ type }}). Les types autorisés sont {{ types }}. This value should be {{ limit }} or less. Cette valeur doit être inférieure ou égale à {{ limit }}. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractères. This value should be {{ limit }} or more. Cette valeur doit être supérieure ou égale à {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractères. This value should not be blank. Cette valeur ne doit pas être vide. This value should not be null. Cette valeur ne doit pas être nulle. This value should be null. Cette valeur doit être nulle. This value is not valid. Cette valeur n'est pas valide. This value is not a valid time. Cette valeur n'est pas une heure valide. This value is not a valid URL. Cette valeur n'est pas une URL valide. The two values should be equal. Les deux valeurs doivent être identiques. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Le fichier est trop volumineux. Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}. The file is too large. Le fichier est trop volumineux. The file could not be uploaded. Le téléchargement de ce fichier est impossible. This value should be a valid number. Cette valeur doit être un nombre. This file is not a valid image. Ce fichier n'est pas une image valide. This is not a valid IP address. Cette adresse IP n'est pas valide. This value is not a valid language. Cette langue n'est pas valide. This value is not a valid locale. Ce paramètre régional n'est pas valide. This value is not a valid country. Ce pays n'est pas valide. This value is already used. Cette valeur est déjà utilisée. The size of the image could not be detected. La taille de l'image n'a pas pu être détectée. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. La largeur de l'image est trop grande ({{ width }}px). La largeur maximale autorisée est de {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. La largeur de l'image est trop petite ({{ width }}px). La largeur minimale attendue est de {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. La hauteur de l'image est trop grande ({{ height }}px). La hauteur maximale autorisée est de {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. La hauteur de l'image est trop petite ({{ height }}px). La hauteur minimale attendue est de {{ min_height }}px. This value should be the user current password. Cette valeur doit être le mot de passe actuel de l'utilisateur. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Cette chaine doit avoir exactement {{ limit }} caractère.|Cette chaine doit avoir exactement {{ limit }} caractères. The file was only partially uploaded. Le fichier a été partiellement transféré. No file was uploaded. Aucun fichier n'a été transféré. No temporary folder was configured in php.ini. Aucun répertoire temporaire n'a été configuré dans le php.ini. Cannot write temporary file to disk. Impossible d'écrire le fichier temporaire sur le disque. A PHP extension caused the upload to fail. Une extension PHP a empêché le transfert du fichier. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Cette collection doit contenir {{ limit }} élément ou plus.|Cette collection doit contenir {{ limit }} éléments ou plus. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Cette collection doit contenir {{ limit }} élément ou moins.|Cette collection doit contenir {{ limit }} éléments ou moins. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Cette collection doit contenir exactement {{ limit }} élément.|Cette collection doit contenir exactement {{ limit }} éléments. Invalid card number. Numéro de carte invalide. Unsupported card type or invalid card number. Type de carte non supporté ou numéro invalide. This is not a valid International Bank Account Number (IBAN). Le numéro IBAN (International Bank Account Number) saisi n'est pas valide. This value is not a valid ISBN-10. Cette valeur n'est pas un code ISBN-10 valide. This value is not a valid ISBN-13. Cette valeur n'est pas un code ISBN-13 valide. This value is neither a valid ISBN-10 nor a valid ISBN-13. Cette valeur n'est ni un code ISBN-10, ni un code ISBN-13 valide. This value is not a valid ISSN. Cette valeur n'est pas un code ISSN valide. This value is not a valid currency. Cette valeur n'est pas une devise valide. This value should be equal to {{ compared_value }}. Cette valeur doit être égale à {{ compared_value }}. This value should be greater than {{ compared_value }}. Cette valeur doit être supérieure à {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Cette valeur doit être supérieure ou égale à {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Cette valeur doit être identique à {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Cette valeur doit être inférieure à {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Cette valeur doit être inférieure ou égale à {{ compared_value }}. This value should not be equal to {{ compared_value }}. Cette valeur ne doit pas être égale à {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Cette valeur ne doit pas être identique à {{ compared_value_type }} {{ compared_value }}. PK]=^::2Validator/Resources/translations/validators.it.xlfnu[ This value should be false. Questo valore dovrebbe essere falso. This value should be true. Questo valore dovrebbe essere vero. This value should be of type {{ type }}. Questo valore dovrebbe essere di tipo {{ type }}. This value should be blank. Questo valore dovrebbe essere vuoto. The value you selected is not a valid choice. Questo valore dovrebbe essere una delle opzioni disponibili. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Si dovrebbe selezionare almeno {{ limit }} opzione.|Si dovrebbero selezionare almeno {{ limit }} opzioni. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Si dovrebbe selezionare al massimo {{ limit }} opzione.|Si dovrebbero selezionare al massimo {{ limit }} opzioni. One or more of the given values is invalid. Uno o più valori inseriti non sono validi. The fields {{ fields }} were not expected. I campi {{ fields }} non sono validi. The fields {{ fields }} are missing. I campi {{ fields }} sono mancanti. This value is not a valid date. Questo valore non è una data valida. This value is not a valid datetime. Questo valore non è una data e ora valida. This value is not a valid email address. Questo valore non è un indirizzo email valido. The file could not be found. Non è stato possibile trovare il file. The file is not readable. Il file non è leggibile. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Il file è troppo grande ({{ size }} {{ suffix }}). La dimensione massima consentita è {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Il mime type del file non è valido ({{ type }}). I tipi permessi sono {{ types }}. This value should be {{ limit }} or less. Questo valore dovrebbe essere {{ limit }} o inferiore. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} carattere.|Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} caratteri. This value should be {{ limit }} or more. Questo valore dovrebbe essere {{ limit }} o superiore. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} carattere.|Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} caratteri. This value should not be blank. Questo valore non dovrebbe essere vuoto. This value should not be null. Questo valore non dovrebbe essere nullo. This value should be null. Questo valore dovrebbe essere nullo. This value is not valid. Questo valore non è valido. This value is not a valid time. Questo valore non è un'ora valida. This value is not a valid URL. Questo valore non è un URL valido. The two values should be equal. I due valori dovrebbero essere uguali. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Il file è troppo grande. La dimensione massima è {{ limit }} {{ suffix }}. The file is too large. Il file è troppo grande. The file could not be uploaded. Il file non può essere caricato. This value should be a valid number. Questo valore dovrebbe essere un numero. This file is not a valid image. Questo file non è una immagine valida. This is not a valid IP address. Questo valore non è un indirizzo IP valido. This value is not a valid language. Questo valore non è una lingua valida. This value is not a valid locale. Questo valore non è una impostazione regionale valida. This value is not a valid country. Questo valore non è una nazione valida. This value is already used. Questo valore è già stato utilizzato. The size of the image could not be detected. La dimensione dell'immagine non può essere determinata. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. La larghezza dell'immagine è troppo grande ({{ width }}px). La larghezza massima è di {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. La larghezza dell'immagine è troppo piccola ({{ width }}px). La larghezza minima è di {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. L'altezza dell'immagine è troppo grande ({{ height }}px). L'altezza massima è di {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. L'altezza dell'immagine è troppo piccola ({{ height }}px). L'altezza minima è di {{ min_height }}px. This value should be the user current password. Questo valore dovrebbe essere la password attuale dell'utente. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Questo valore dovrebbe contenere esattamente {{ limit }} carattere.|Questo valore dovrebbe contenere esattamente {{ limit }} caratteri. The file was only partially uploaded. Il file è stato caricato solo parzialmente. No file was uploaded. Nessun file è stato caricato. No temporary folder was configured in php.ini. Nessuna cartella temporanea è stata configurata nel php.ini. Cannot write temporary file to disk. Impossibile scrivere il file temporaneo sul disco. A PHP extension caused the upload to fail. Un'estensione PHP ha causato il fallimento del caricamento. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Questa collezione dovrebbe contenere almeno {{ limit }} elemento.|Questa collezione dovrebbe contenere almeno {{ limit }} elementi. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Questa collezione dovrebbe contenere massimo {{ limit }} elemento.|Questa collezione dovrebbe contenere massimo {{ limit }} elementi. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Questa collezione dovrebbe contenere esattamente {{ limit }} elemento.|Questa collezione dovrebbe contenere esattamente {{ limit }} elementi. Invalid card number. Numero di carta non valido. Unsupported card type or invalid card number. Tipo di carta non supportato o numero non valido. This is not a valid International Bank Account Number (IBAN). Questo valore non è un IBAN (International Bank Account Number) valido. This value is not a valid ISBN-10. Questo valore non è un codice ISBN-10 valido. This value is not a valid ISBN-13. Questo valore non è un codice ISBN-13 valido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Questo valore non è un codice ISBN-10 o ISBN-13 valido. This value is not a valid ISSN. Questo valore non è un codice ISSN valido. This value is not a valid currency. Questo valore non è una valuta valida. PK] AA2Validator/Resources/translations/validators.ca.xlfnu[ This value should be false. Aquest valor hauria de ser fals. This value should be true. Aquest valor hauria de ser cert. This value should be of type {{ type }}. Aquest valor hauria de ser del tipus {{ type }}. This value should be blank. Aquest valor hauria d'estar buit. The value you selected is not a valid choice. El valor seleccionat no és una opció vàlida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Ha de seleccionar almenys {{ limit }} opció.|Ha de seleccionar almenys {{ limit }} opcions. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Ha de seleccionar com a màxim {{ limit }} opció.|Ha de seleccionar com a màxim {{ limit }} opcions. One or more of the given values is invalid. Un o més dels valors facilitats són incorrectes. The fields {{ fields }} were not expected. No s'esperaven els camps {{ fields }}. The fields {{ fields }} are missing. Falten els camps {{ fields }}. This value is not a valid date. Aquest valor no és una data vàlida. This value is not a valid datetime. Aquest valor no és una data i hora vàlida. This value is not a valid email address. Aquest valor no és una adreça d'email vàlida. The file could not be found. No s'ha pogut trobar l'arxiu. The file is not readable. No es pot llegir l'arxiu. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. L'arxiu és massa gran ({{ size }} {{ suffix }}). La grandària màxima permesa és {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. El tipus mime de l'arxiu no és vàlid ({{ type }}). Els tipus mime vàlids són {{ types }}. This value should be {{ limit }} or less. Aquest valor hauria de ser {{ limit }} o menys. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcter o menys.|Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcters o menys. This value should be {{ limit }} or more. Aquest valor hauria de ser {{ limit }} o més. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Aquest valor és massa curt. Hauria de tenir {{ limit }} caràcters o més. This value should not be blank. Aquest valor no hauria d'estar buit. This value should not be null. Aquest valor no hauria de ser null. This value should be null. Aquest valor hauria de ser null. This value is not valid. Aquest valor no és vàlid. This value is not a valid time. Aquest valor no és una hora vàlida. This value is not a valid URL. Aquest valor no és una URL vàlida. The two values should be equal. Els dos valors haurien de ser iguals. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. L'arxiu és massa gran. El tamany màxim permés és {{ limit }} {{ suffix }}. The file is too large. L'arxiu és massa gran. The file could not be uploaded. No es pot pujar l'arxiu. This value should be a valid number. Aquest valor hauria de ser un nombre vàlid. This file is not a valid image. L'arxiu no és una imatge vàlida. This is not a valid IP address. Això no és una adreça IP vàlida. This value is not a valid language. Aquest valor no és un idioma vàlid. This value is not a valid locale. Aquest valor no és una localització vàlida. This value is not a valid country. Aquest valor no és un país vàlid. This value is already used. Aquest valor ja s'ha utilitzat. The size of the image could not be detected. No s'ha pogut determinar la grandària de la imatge. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. L'amplària de la imatge és massa gran ({{ width }}px). L'amplària màxima permesa són {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. L'amplària de la imatge és massa petita ({{ width }}px). L'amplària mínima requerida són {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. L'altura de la imatge és massa gran ({{ height }}px). L'altura màxima permesa són {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. L'altura de la imatge és massa petita ({{ height }}px). L'altura mínima requerida són {{ min_height }}px. This value should be the user current password. Aquest valor hauria de ser la contrasenya actual de l'usuari. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Aquest valor hauria de tenir exactament {{ limit }} caràcter.|Aquest valor hauria de tenir exactament {{ limit }} caràcters. The file was only partially uploaded. L'arxiu va ser només pujat parcialment. No file was uploaded. Cap arxiu va ser pujat. No temporary folder was configured in php.ini. Cap carpeta temporal va ser configurada en php.ini. Cannot write temporary file to disk. No es va poder escriure l'arxiu temporal en el disc. A PHP extension caused the upload to fail. Una extensió de PHP va fer que la pujada fallara. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Aquesta col·lecció ha de contenir {{ limit }} element o més.|Aquesta col·lecció ha de contenir {{ limit }} elements o més. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Aquesta col·lecció ha de contenir {{ limit }} element o menys.|Aquesta col·lecció ha de contenir {{ limit }} elements o menys. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Aquesta col·lecció ha de contenir exactament {{ limit }} element.|Aquesta col·lecció ha de contenir exactament {{ limit }} elements. Invalid card number. Número de targeta invàlid. Unsupported card type or invalid card number. Tipus de targeta no suportada o número de targeta invàlid. This is not a valid International Bank Account Number (IBAN). Això no és un nombre de compte bancari internacional (IBAN) vàlid. This value is not a valid ISBN-10. Aquest valor no és un ISBN-10 vàlid. This value is not a valid ISBN-13. Aquest valor no és un ISBN-13 vàlid. This value is neither a valid ISBN-10 nor a valid ISBN-13. Aquest valor no és ni un ISBN-10 vàlid ni un ISBN-13 vàlid. This value is not a valid ISSN. Aquest valor no és un ISSN vàlid. This value is not a valid currency. Aquest valor no és una divisa vàlida. This value should be equal to {{ compared_value }}. Aquest valor hauria de ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Aquest valor hauria de ser més gran a {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Aquest valor hauria de ser major o igual a {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Aquest valor hauria de ser idèntic a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Aquest valor hauria de ser menor a {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Aquest valor hauria de ser menor o igual a {{ compared_value }}. This value should not be equal to {{ compared_value }}. Aquest valor no hauria de ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Aquest valor no hauria de idèntic a {{ compared_value_type }} {{ compared_value }}. PK]112Validator/Resources/translations/validators.no.xlfnu[ This value should be false. Verdien skulle ha vore tom/nei. This value should be true. Verdien skulla ha vore satt/ja. This value should be of type {{ type }}. Verdien må vere av typen {{ type }}. This value should be blank. Verdien skal vere blank. The value you selected is not a valid choice. Verdien du valgte er ikkje gyldig. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du må velge minst {{ limit }} valg. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan maksimalt gjere {{ limit }} valg. One or more of the given values is invalid. Ein eller fleire av dei opplyste verdiane er ugyldige. The fields {{ fields }} were not expected. Felta {{ fields }} var ikkje forventa. The fields {{ fields }} are missing. Felta {{ fields }} manglar. This value is not a valid date. Verdien er ikkje ein gyldig dato. This value is not a valid datetime. Verdien er ikkje ein gyldig dato og tid. This value is not a valid email address. Verdien er ikkje ei gyldig e-postadresse. The file could not be found. Fila kunne ikkje finnes. The file is not readable. Fila kan ikkje lesast. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fila er for stor ({{ size }} {{ suffix }}). Tillatt maksimal størrelse er {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime-typen av fila er ugyldig ({{ type }}). Tillatte mime-typar er {{ types }}. This value should be {{ limit }} or less. Verdien må vere {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Verdien er for lang. Den må vere {{ limit }} bokstavar eller mindre. This value should be {{ limit }} or more. Verdien må vere {{ limit }} eller meir. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Verdien er for kort. Den må ha {{ limit }} teikn eller fleire. This value should not be blank. Verdien må ikkje vere blank. This value should not be null. Verdien må ikkje vere tom (null). This value should be null. Verdien må vere tom (null). This value is not valid. Verdien er ikkje gyldig. This value is not a valid time. Verdien er ikkje gyldig tidseining. This value is not a valid URL. Verdien er ikkje ein gyldig URL. The two values should be equal. Dei to verdiane må vere like. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fila er for stor. Den maksimale storleik er {{ limit }} {{ suffix }}. The file is too large. Fila er for stor. The file could not be uploaded. Fila kunne ikkje bli lasta opp. This value should be a valid number. Verdien må vere eit gyldig tal. This file is not a valid image. Fila er ikkje eit gyldig bilete. This is not a valid IP address. Dette er ikkje ei gyldig IP-adresse. This value is not a valid language. Verdien er ikkje eit gyldig språk. This value is not a valid locale. Verdien er ikkje ein gyldig lokalitet (språk/region). This value is not a valid country. Verdien er ikkje eit gyldig land. This value is already used. Verdien er allereie i bruk. The size of the image could not be detected. Storleiken på biletet kunne ikkje oppdagast. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Biletbreidda er for stor, ({{ width }} pikslar). Tillatt maksimumsbreidde er {{ max_width }} pikslar. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Biletbreidda er for liten, ({{ width }} pikslar). Forventa minimumsbreidde er {{ min_width }} pikslar. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Bilethøgda er for stor, ({{ height }} pikslar). Tillatt maksimumshøgde er {{ max_height }} pikslar. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Billethøgda er for låg, ({{ height }} pikslar). Forventa minimumshøgde er {{ min_height }} pikslar. This value should be the user current password. Verdien må vere brukaren sitt noverande passord. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Verdien må vere nøyaktig {{ limit }} teikn. The file was only partially uploaded. Fila vart kun delvis opplasta. No file was uploaded. Inga fil vart lasta opp. No temporary folder was configured in php.ini. Førebels mappe (tmp) er ikkje konfigurert i php.ini. Cannot write temporary file to disk. Kan ikkje skrive førebels fil til disk. A PHP extension caused the upload to fail. Ei PHP-udviding forårsaka feil under opplasting. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Denne samlinga må innehalde {{ limit }} element eller meir.|Denne samlinga må innehalde {{ limit }} element eller meir. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Denne samlinga må innehalde {{ limit }} element eller færre.|Denne samlinga må innehalde {{ limit }} element eller færre. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Denne samlinga må innehalde nøyaktig {{ limit }} element.|Denne samlinga må innehalde nøyaktig {{ limit }} element. Invalid card number. Ugyldig kortnummer. Unsupported card type or invalid card number. Korttypen er ikkje støtta eller ugyldig kortnummer. PK] This value should be false. Стойността трябва да бъде лъжа (false). This value should be true. Стойността трябва да бъде истина (true). This value should be of type {{ type }}. Стойността трябва да бъде от тип {{ type }}. This value should be blank. Стойността трябва да бъде празна. The value you selected is not a valid choice. Избраната стойност е невалидна. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Трябва да изберете поне {{ limit }} опция.|Трябва да изберете поне {{ limit }} опции. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Трябва да изберете най-много {{ limit }} опция.|Трябва да изберете най-много {{ limit }} опции. One or more of the given values is invalid. Една или повече от зададените стойности е невалидна. The fields {{ fields }} were not expected. Полетата {{ fields }} не бяха очаквани. The fields {{ fields }} are missing. Полетата {{ fields }} липсват. This value is not a valid date. Стойността не е валидна дата (date). This value is not a valid datetime. Стойността не е валидна дата (datetime). This value is not a valid email address. Стойността не е валиден email адрес. The file could not be found. Файлът не беше открит. The file is not readable. Файлът не може да бъде прочетен. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файлът е твърде голям ({{ size }} {{ suffix }}). Максималният размер е {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Майм типа на файла е невалиден ({{ type }}). Разрешени майм типове са {{ types }}. This value should be {{ limit }} or less. Стойността трябва да бъде {{ limit }} или по-малко. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символ.|Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символа. This value should be {{ limit }} or more. Стойността трябва да бъде {{ limit }} или повече. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символ.|Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символа. This value should not be blank. Стойността не трябва да бъде празна. This value should not be null. Стойността не трябва да бъде null. This value should be null. Стойността трябва да бъде null. This value is not valid. Стойността не е валидна. This value is not a valid time. Стойността не е валидно време (time). This value is not a valid URL. Стойността не е валиден URL. The two values should be equal. Двете стойности трябва да бъдат равни. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файлът е твърде голям. Разрешеният максимален размер е {{ limit }} {{ suffix }}. The file is too large. Файлът е твърде голям. The file could not be uploaded. Файлът не може да бъде качен. This value should be a valid number. Стойността трябва да бъде валиден номер. This file is not a valid image. Файлът не е валидно изображение. This is not a valid IP address. Това не е валиден IP адрес. This value is not a valid language. Стойността не е валиден език. This value is not a valid locale. Стойността не е валидна локализация. This value is not a valid country. Стойността не е валидна държава. This value is already used. Стойността вече е в употреба. The size of the image could not be detected. Размера на изображението не може да бъде определен. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Изображението е твърде широко ({{ width }}px). Широчината трябва да бъде максимум {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Изображението е с твърде малка широчина ({{ width }}px). Широчината трябва да бъде минимум {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Изображението е с твърде голяма височина ({{ height }}px). Височината трябва да бъде максимум {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Изображението е с твърде малка височина ({{ height }}px). Височина трябва да бъде минимум {{ min_height }}px. This value should be the user current password. Стойността трябва да бъде текущата потребителска парола. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Стойността трябва да бъде точно {{ limit }} символ.|Стойността трябва да бъде точно {{ limit }} символа. The file was only partially uploaded. Файлът е качен частично. No file was uploaded. Файлът не беше качен. No temporary folder was configured in php.ini. Не е посочена директория за временни файлове в php.ini. Cannot write temporary file to disk. Не може да запише временен файл на диска. A PHP extension caused the upload to fail. PHP разширение предизвика прекъсване на качването. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Колекцията трябва да съдържа поне {{ limit }} елемент.|Колекцията трябва да съдържа поне {{ limit }} елемента. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Колекцията трябва да съдържа най-много {{ limit }} елемент.|Колекцията трябва да съдържа най-много {{ limit }} елемента. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Колекцията трябва да съдържа точно {{ limit }} елемент.|Колекцията трябва да съдържа точно {{ limit }} елемента. Invalid card number. Невалиден номер на картата. Unsupported card type or invalid card number. Неподдържан тип карта или невалиден номер на картата. This is not a valid International Bank Account Number (IBAN). Невалиден Международен номер на банкова сметка (IBAN). This value is not a valid ISBN-10. Невалиден ISBN-10. This value is not a valid ISBN-13. Невалиден ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Невалидна стойност както за ISBN-10, така и за ISBN-13 . This value is not a valid ISSN. Невалиден Международен стандартен сериен номер (ISSN). This value is not a valid currency. Невалидна валута. This value should be equal to {{ compared_value }}. Стойността трябва да бъде равна на {{ compared_value }}. This value should be greater than {{ compared_value }}. Стойността трябва да бъде по-голяма от {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Стойността трябва да бъде по-голяма или равна на {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Стойността трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Стойността трябва да бъде по-малка {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Стойността трябва да бъде по-малка или равна на {{ compared_value }}. This value should not be equal to {{ compared_value }}. Стойността не трябва да бъде равна на {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Стойността не трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}. PK]tAA2Validator/Resources/translations/validators.eu.xlfnu[ This value should be false. Balio hau faltsua izan beharko litzateke. This value should be true. Balio hau egia izan beharko litzateke. This value should be of type {{ type }}. Balio hau {{ type }} motakoa izan beharko litzateke. This value should be blank. Balio hau hutsik egon beharko litzateke. The value you selected is not a valid choice. Hautatu duzun balioa ez da aukera egoki bat. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Gutxienez aukera {{ limit }} hautatu behar duzu.|Gutxienez {{ limit }} aukera hautatu behar dituzu. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Gehienez aukera {{ limit }} hautatu behar duzu.|Gehienez {{ limit }} aukera hautatu behar dituzu. One or more of the given values is invalid. Emandako balioetatik gutxienez bat ez da egokia. The fields {{ fields }} were not expected. {{ fields }} eremuak ez ziren espero. The fields {{ fields }} are missing. {{ fields }} eremuak falta dira. This value is not a valid date. Balio hau ez da data egoki bat. This value is not a valid datetime. Balio hau ez da data-ordu egoki bat. This value is not a valid email address. Balio hau ez da posta elektroniko egoki bat. The file could not be found. Ezin izan da fitxategia aurkitu. The file is not readable. Fitxategia ez da irakurgarria. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fitxategia handiegia da ({{ size }} {{ suffix }}). Baimendutako tamaina handiena {{ limit }} {{ suffix }} da. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Fitxategiaren mime mota ez da egokia ({{ type }}). Hauek dira baimendutako mime motak: {{ types }}. This value should be {{ limit }} or less. Balio hau gehienez {{ limit }} izan beharko litzateke. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Balio hau luzeegia da. Gehienez karaktere {{ limit }} eduki beharko luke.|Balio hau luzeegia da. Gehienez {{ limit }} karaktere eduki beharko lituzke. This value should be {{ limit }} or more. Balio hau gutxienez {{ limit }} izan beharko litzateke. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Balio hau motzegia da. Karaktere {{ limit }} gutxienez eduki beharko luke.|Balio hau motzegia da. Gutxienez {{ limit }} karaktere eduki beharko lituzke. This value should not be blank. Balio hau ez litzateke hutsik egon behar. This value should not be null. Balio hau ez litzateke nulua izan behar. This value should be null. Balio hau nulua izan beharko litzateke. This value is not valid. Balio hau ez da egokia. This value is not a valid time. Balio hau ez da ordu egoki bat. This value is not a valid URL. Balio hau ez da baliabideen kokatzaile uniforme (URL) egoki bat. The two values should be equal. Bi balioak berdinak izan beharko lirateke. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fitxategia handiegia da. Baimendutako tamaina handiena {{ limit }} {{ suffix }} da. The file is too large. Fitxategia handiegia da. The file could not be uploaded. Ezin izan da fitxategia igo. This value should be a valid number. Balio hau zenbaki egoki bat izan beharko litzateke. This file is not a valid image. Fitxategi hau ez da irudi egoki bat. This is not a valid IP address. Honako hau ez da IP helbide egoki bat. This value is not a valid language. Balio hau ez da hizkuntza egoki bat. This value is not a valid locale. Balio hau ez da kokapen egoki bat. This value is not a valid country. Balio hau ez da herrialde egoki bat. This value is already used. Balio hau jadanik erabilia izan da. The size of the image could not be detected. Ezin izan da irudiaren tamaina detektatu. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Irudiaren zabalera handiegia da ({{ width }}px). Onartutako gehienezko zabalera {{ max_width }}px dira. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Irudiaren zabalera txikiegia da ({{ width }}px). Onartutako gutxieneko zabalera {{ min_width }}px dira. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Irudiaren altuera handiegia da ({{ height }}px). Onartutako gehienezko altuera {{ max_height }}px dira. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Irudiaren altuera txikiegia da ({{ height }}px). Onartutako gutxieneko altuera {{ min_height }}px dira. This value should be the user current password. Balio hau uneko erabiltzailearen pasahitza izan beharko litzateke. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Balio honek zehazki karaktere {{ limit }} izan beharko luke.|Balio honek zehazki {{ limit }} karaktere izan beharko lituzke. The file was only partially uploaded. Fitxategiaren zati bat bakarrik igo da. No file was uploaded. Ez da fitxategirik igo. No temporary folder was configured in php.ini. Ez da aldi baterako karpetarik konfiguratu php.ini fitxategian. Cannot write temporary file to disk. Ezin izan da aldi baterako fitxategia diskoan idatzi. A PHP extension caused the upload to fail. PHP luzapen batek igoeraren hutsa eragin du. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Bilduma honek gutxienez elementu {{ limit }} eduki beharko luke.|Bilduma honek gutxienez {{ limit }} elementu eduki beharko lituzke. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Bilduma honek gehienez elementu {{ limit }} eduki beharko luke.|Bilduma honek gehienez {{ limit }} elementu eduki beharko lituzke. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Bilduma honek zehazki elementu {{ limit }} eduki beharko luke.|Bilduma honek zehazki {{ limit }} elementu eduki beharko lituzke. Invalid card number. Txartel zenbaki baliogabea. Unsupported card type or invalid card number. Txartel mota onartezina edo txartel zenbaki baliogabea. This is not a valid International Bank Account Number (IBAN). Hau ez da baliozko banku internazionaleko kontu zenbaki (IBAN) bat. This value is not a valid ISBN-10. Balio hau ez da onartutako ISBN-10 bat. This value is not a valid ISBN-13. Balio hau ez da onartutako ISBN-13 bat. This value is neither a valid ISBN-10 nor a valid ISBN-13. Balio hau ez da onartutako ISBN-10 edo ISBN-13 bat. This value is not a valid ISSN. Balio hau ez da onartutako ISSN bat. This value is not a valid currency. Balio hau ez da baliozko moneta bat. This value should be equal to {{ compared_value }}. Balio hau {{ compared_value }}-(r)en berbera izan beharko litzateke. This value should be greater than {{ compared_value }}. Balio hau {{ compared_value }} baino handiagoa izan beharko litzateke. This value should be greater than or equal to {{ compared_value }}. Balio hau {{ compared_value }}-(r)en berdina edota handiagoa izan beharko litzateke. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Balio hau {{ compared_value_type }} {{ compared_value }}-(r)en berbera izan beharko litzateke. This value should be less than {{ compared_value }}. Balio hau {{ compared_value }} baino txikiagoa izan beharko litzateke. This value should be less than or equal to {{ compared_value }}. Balio hau {{ compared_value }}-(r)en berdina edota txikiagoa izan beharko litzateke. This value should not be equal to {{ compared_value }}. Balio hau ez litzateke {{ compared_value }}-(r)en berdina izan behar. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Balio hau ez litzateke {{ compared_value_type }} {{ compared_value }}-(r)en berbera izan behar. PK]-L>L>2Validator/Resources/translations/validators.id.xlfnu[ This value should be false. Nilai ini harus bernilai salah. This value should be true. Nilai ini harus bernilai benar. This value should be of type {{ type }}. Nilai ini harus bertipe {{ type }}. This value should be blank. Nilai ini harus kosong. The value you selected is not a valid choice. Nilai yang dipilih tidak tepat. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Anda harus memilih paling tidak {{ limit }} pilihan. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Anda harus memilih paling banyak {{ limit }} pilihan. One or more of the given values is invalid. Satu atau lebih nilai yang diberikan tidak sah. The fields {{ fields }} were not expected. Kolom {{ fields }} tidak seperti yang diharapkan. The fields {{ fields }} are missing. Kolom {{ fields }} hilang. This value is not a valid date. Nilai ini bukan merupakan tanggal yang sah. This value is not a valid datetime. Nilai ini bukan merupakan tanggal dan waktu yang sah. This value is not a valid email address. Nilai ini bukan alamat email yang sah. The file could not be found. Berkas tidak ditemukan. The file is not readable. Berkas tidak bisa dibaca. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Ukuran berkas terlalu besar ({{ size }} {{ suffix }}). Ukuran maksimum yang diizinkan adalah {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Jenis berkas ({{ type }}) tidak sah. Jenis berkas yang diijinkan adalah {{ types }}. This value should be {{ limit }} or less. Nilai ini harus {{ limit }} atau kurang. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Nilai ini terlalu panjang. Seharusnya {{ limit }} karakter atau kurang. This value should be {{ limit }} or more. Nilai ini harus {{ limit }} atau lebih. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Nilai ini terlalu pendek. Seharusnya {{ limit }} karakter atau lebih. This value should not be blank. Nilai ini tidak boleh kosong. This value should not be null. Nilai ini tidak boleh 'null'. This value should be null. Nilai ini harus 'null'. This value is not valid. Nilai ini tidak sah. This value is not a valid time. Nilai ini bukan merupakan waktu yang sah. This value is not a valid URL. Nilai ini bukan URL yang sah. The two values should be equal. Isi keduanya harus sama. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ukuran berkas terlalu besar. Ukuran maksimum yang diijinkan adalah {{ limit }} {{ suffix }}. The file is too large. Ukuran berkas terlalu besar. The file could not be uploaded. Berkas tidak dapat diunggah. This value should be a valid number. Nilai ini harus angka yang sah. This file is not a valid image. Berkas ini tidak termasuk gambar. This is not a valid IP address. Ini bukan alamat IP yang sah. This value is not a valid language. Nilai ini bukan bahasa yang sah. This value is not a valid locale. Nilai ini bukan lokal yang sah. This value is not a valid country. Nilai ini bukan negara yang sah. This value is already used. Nilai ini sudah digunakan. The size of the image could not be detected. Ukuran dari gambar tidak bisa dideteksi. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Lebar gambar terlalu besar ({{ width }}px). Ukuran lebar maksimum adalah {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Lebar gambar terlalu kecil ({{ width}}px). Ukuran lebar minimum yang diharapkan adalah {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Tinggi gambar terlalu besar ({{ height }}px). Ukuran tinggi maksimum adalah {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Tinggi gambar terlalu kecil ({{ height }}px). Ukuran tinggi minimum yang diharapkan adalah {{ min_height }}px. This value should be the user current password. Nilai ini harus kata sandi pengguna saat ini. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Nilai ini harus memiliki tepat {{ limit }} karakter. The file was only partially uploaded. Berkas hanya terunggah sebagian. No file was uploaded. Tidak ada berkas terunggah. No temporary folder was configured in php.ini. Direktori sementara tidak dikonfiguasi pada php.ini. Cannot write temporary file to disk. Tidak dapat menuliskan berkas sementara ke dalam media penyimpanan. A PHP extension caused the upload to fail. Sebuah ekstensi PHP menyebabkan kegagalan unggah. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Kumpulan ini harus memiliki {{ limit }} elemen atau lebih. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Kumpulan ini harus memiliki kurang dari {{ limit }} elemen. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Kumpulan ini harus memiliki tepat {{ limit }} elemen. Invalid card number. Nomor kartu tidak sah. Unsupported card type or invalid card number. Jenis kartu tidak didukung atau nomor kartu tidak sah. This is not a valid International Bank Account Number (IBAN). Ini bukan Nomor Rekening Bank Internasional (IBAN) yang sah. This value is not a valid ISBN-10. Nilai ini bukan ISBN-10 yang sah. This value is not a valid ISBN-13. Nilai ini bukan ISBN-13 yang sah. This value is neither a valid ISBN-10 nor a valid ISBN-13. Nilai ini bukan ISBN-10 maupun ISBN-13 yang sah. This value is not a valid ISSN. Nilai ini bukan ISSN yang sah. This value is not a valid currency. Nilai ini bukan mata uang yang sah. This value should be equal to {{ compared_value }}. Nilai ini seharusnya sama dengan {{ compared_value }}. This value should be greater than {{ compared_value }}. Nilai ini seharusnya lebih dari {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Nilai ini seharusnya lebih dari atau sama dengan {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Nilai ini seharusnya identik dengan {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Nilai ini seharusnya kurang dari {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Nilai ini seharusnya kurang dari atau sama dengan {{ compared_value }}. This value should not be equal to {{ compared_value }}. Nilai ini seharusnya tidak sama dengan {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Nilai ini seharusnya tidak identik dengan {{ compared_value_type }} {{ compared_value }}. PK]%N==2Validator/Resources/translations/validators.et.xlfnu[ This value should be false. Väärtus peaks olema väär. This value should be true. Väärtus peaks oleme tõene. This value should be of type {{ type }}. Väärtus peaks olema {{ type }}-tüüpi. This value should be blank. Väärtus peaks olema tühi. The value you selected is not a valid choice. Väärtus peaks olema üks etteantud valikutest. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Valima peaks vähemalt {{ limit }} valikut. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Valima peaks mitte rohkem kui {{ limit }} valikut. One or more of the given values is invalid. One or more of the given values is invalid. The fields {{ fields }} were not expected. Väljad {{ fields }} olid ootamatud. The fields {{ fields }} are missing. Väljad {{ fields }} on puudu. This value is not a valid date. Väärtus pole korrektne kuupäev. This value is not a valid datetime. Väärtus pole korrektne kuupäev ja kellaeg. This value is not a valid email address. Väärtus pole korrektne e-maili aadress. The file could not be found. Faili ei leita. The file is not readable. Fail ei ole loetav. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fail on liiga suur ({{ size }} {{ suffix }}). Suurim lubatud suurus on {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Faili sisutüüp on vigane ({{ type }}). Lubatud sisutüübid on {{ types }}. This value should be {{ limit }} or less. Väärtus peaks olema {{ limit }} või vähem. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Väärtus on liiga pikk. Pikkus peaks olema {{ limit }} tähemärki või vähem. This value should be {{ limit }} or more. Väärtus peaks olema {{ limit }} või rohkem. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Väärtus on liiga lühike. Pikkus peaks olema {{ limit }} tähemärki või rohkem. This value should not be blank. Väärtus ei tohiks olla tühi. This value should not be null. Väärtus ei tohiks olla 'null'. This value should be null. Väärtus peaks olema 'null'. This value is not valid. Väärtus on vigane. This value is not a valid time. Väärtus pole korrektne aeg. This value is not a valid URL. Väärtus pole korrektne URL. The two values should be equal. Väärtused peaksid olema võrdsed. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fail on liiga suur. Maksimaalne lubatud suurus on {{ limit }} {{ suffix }}. The file is too large. Fail on liiga suur. The file could not be uploaded. Faili ei saa üles laadida. This value should be a valid number. Väärtus peaks olema korrektne number. This file is not a valid image. Fail ei ole korrektne pilt. This is not a valid IP address. IP aadress pole korrektne. This value is not a valid language. Väärtus pole korrektne keel. This value is not a valid locale. Väärtus pole korrektne asukohakeel. This value is not a valid country. Väärtus pole olemasolev riik. This value is already used. Väärtust on juba kasutatud. The size of the image could not be detected. Pildi suurust polnud võimalik tuvastada. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Pilt on liiga lai ({{ width }}px). Suurim lubatud laius on {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Pilt on liiga kitsas ({{ width }}px). Vähim lubatud laius on {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Pilt on liiga pikk ({{ height }}px). Lubatud suurim pikkus on {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Pilt pole piisavalt pikk ({{ height }}px). Lubatud vähim pikkus on {{ min_height }}px. This value should be the user current password. Väärtus peaks olema kasutaja kehtiv salasõna. This value should have exactly {{ limit }} characters. Väärtus peaks olema täpselt {{ limit }} tähemärk pikk.|Väärtus peaks olema täpselt {{ limit }} tähemärki pikk. The file was only partially uploaded. Fail ei laetud täielikult üles. No file was uploaded. Ühtegi faili ei laetud üles. No temporary folder was configured in php.ini. Ühtegi ajutist kausta polnud php.ini-s seadistatud. Cannot write temporary file to disk. Ajutist faili ei saa kettale kirjutada. A PHP extension caused the upload to fail. PHP laiendi tõttu ebaõnnestus faili üleslaadimine. This collection should contain {{ limit }} elements or more. Kogumikus peaks olema vähemalt {{ limit }} element.|Kogumikus peaks olema vähemalt {{ limit }} elementi. This collection should contain {{ limit }} elements or less. Kogumikus peaks olema ülimalt {{ limit }} element.|Kogumikus peaks olema ülimalt {{ limit }} elementi. This collection should contain exactly {{ limit }} elements. Kogumikus peaks olema täpselt {{ limit }} element.|Kogumikus peaks olema täpselt {{ limit }}|elementi. Invalid card number. Vigane kaardi number. Unsupported card type or invalid card number. Kaardi tüüpi ei toetata või kaardi number on vigane. This is not a valid International Bank Account Number (IBAN). Väärtus pole korrektne IBAN-number. This value is not a valid ISBN-10. Väärtus pole korrektne ISBN-10. This value is not a valid ISBN-13. Väärtus pole korrektne ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Väärtus pole korrektne ISBN-10 ega ISBN-13. This value is not a valid ISSN. Väärtus pole korrektne ISSN. This value is not a valid currency. Väärtus pole korrektne valuuta. This value should be equal to {{ compared_value }}. Väärtus peaks olema võrdne {{ compared_value }}-ga. This value should be greater than {{ compared_value }}. Väärtus peaks olema suurem kui {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Väärtus peaks olema suurem kui või võrduma {{ compared_value }}-ga. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Väärtus peaks olema identne väärtusega {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Väärtus peaks olema väiksem kui {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Väärtus peaks olema väiksem kui või võrduma {{ compared_value }}-ga. This value should not be equal to {{ compared_value }}. Väärtus ei tohiks võrduda {{ compared_value }}-ga. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Väärtus ei tohiks olla identne väärtusega {{ compared_value_type }} {{ compared_value }}. PK] GG2Validator/Resources/translations/validators.fa.xlfnu[ This value should be false. این مقدار باید نادرست(False) باشد. This value should be true. این مقدار باید درست(True) باشد. This value should be of type {{ type }}. این مقدار باید از نوع {{ type }} باشد. This value should be blank. این فیلد باید خالی باشد. The value you selected is not a valid choice. گزینه انتخابی معتبر نیست. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. باید حداقل {{ limit }} گزینه انتخاب کنید.|باید حداقل {{ limit }} گزینه انتخاب کنید. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. حداکثر {{ limit }} گزینه می توانید انتخاب کنید.|حداکثر {{ limit }} گزینه می توانید انتخاب کنید. One or more of the given values is invalid. یک یا چند مقدار نامعتبر وجود دارد. The fields {{ fields }} were not expected. فیلدهای {{ fields }} اضافی هستند. The fields {{ fields }} are missing. فیلدهای {{ fields }} کم هستند. This value is not a valid date. این مقدار یک تاریخ معتبر نیست. This value is not a valid datetime. این مقدار یک تاریخ و زمان معتبر نیست. This value is not a valid email address. این یک رایانامه معتبر نیست. The file could not be found. فایل پیدا نشد. The file is not readable. فایل قابلیت خواندن ندارد. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. فایل بیش از اندازه بزرگ است({{ size }} {{ suffix }}). حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. این نوع فایل مجاز نیست({{ type }}). نوع های مجاز {{ types }} هستند. This value should be {{ limit }} or less. این مقدار باید کوچکتر یا مساوی {{ limit }} باشد. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است.|بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است. This value should be {{ limit }} or more. این مقدار باید برابر و یا بیشتر از {{ limit }} باشد. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد.|بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد. This value should not be blank. این مقدار نباید تهی باشد. This value should not be null. باید مقداری داشته باشد.. This value should be null. نباید مقداری داشته باشد. This value is not valid. این مقدار معتبر نیست. This value is not a valid time. این مقدار یک زمان صحیح نیست. This value is not a valid URL. این یک URL معتبر نیست. The two values should be equal. دو مقدار باید برابر باشند. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. فایل بیش از اندازه بزرگ است. حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است. The file is too large. فایل بیش از اندازه بزرگ است. The file could not be uploaded. بارگذاری فایل با شکست مواجه شد. This value should be a valid number. این مقدار باید یک عدد معتبر باشد. This file is not a valid image. این فایل یک تصویر نیست. This is not a valid IP address. این مقدار یک IP معتبر نیست. This value is not a valid language. این مقدار یک زبان صحیح نیست. This value is not a valid locale. این مقدار یک محل صحیح نیست. This value is not a valid country. این مقدار یک کشور صحیح نیست. This value is already used. این مقدار قبلا مورد استفاده قرار گرفته است. The size of the image could not be detected. اندازه تصویر قابل شناسایی نیست. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. طول تصویر بسیار بزرگ است ({{ width }}px). بشینه طول مجاز {{ max_width }}px است. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. طول تصویر بسیار کوچک است ({{ width }}px). کمینه طول موردنظر {{ min_width }}px است. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. ارتفاع تصویر بسیار بزرگ است ({{ height }}px). بشینه ارتفاع مجاز {{ max_height }}px است. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. ارتفاع تصویر بسیار کوچک است ({{ height }}px). کمینه ارتفاع موردنظر {{ min_height }}px است. This value should be the user current password. این مقدار می بایست کلمه عبور کنونی کاربر باشد. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. این مقدار می بایست دقیفا {{ limit }} کاراکتر داشته باشد.|این مقدرا می بایشت دقیقا {{ limit }} کاراکتر داشته باشد. The file was only partially uploaded. فایل به صورت جزیی بارگذاری شده است. No file was uploaded. هیچ فایلی بارگذاری نشد. No temporary folder was configured in php.ini. فولدر موقت در php.ini پیکربندی نشده است. Cannot write temporary file to disk. فایل موقت را نمی توان در دیسک نوشت. A PHP extension caused the upload to fail. اکستنشن PHP موجب شد که بارگذاری فایل با شکست مواجه شود. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. این مجموعه می بایست دارای حداقل {{ limit }} عنصر یا کمتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا کمتر باشد. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. این مجموعه می بایست به طور دقیق دارا {{ limit }} عنصر باشد.|این مجموعه می بایست به طور دقیق دارای {{ limit }} قلم باشد. Invalid card number. شماره کارت نامعتبر است. Unsupported card type or invalid card number. نوع کارت پشتیبانی نمی شود یا شماره کارت نامعتبر است. This is not a valid International Bank Account Number (IBAN). این یک شماره حساب بین المللی بانک (IBAN) درست نیست. This value is not a valid ISBN-10. این مقدار یک ISBN-10 درست نیست. This value is not a valid ISBN-13. این مقدار یک ISBN-13 درست نیست. This value is neither a valid ISBN-10 nor a valid ISBN-13. این مقدار یک ISBN-10 درست یا ISBN-13 درست نیست. This value is not a valid ISSN. این مقدار یک ISSN درست نیست. This value is not a valid currency. این مقدار یک یکای پول درست نیست. This value should be equal to {{ compared_value }}. این مقدار باید برابر با {{ compared_value }} باشد. This value should be greater than {{ compared_value }}. این مقدار باید از {{ compared_value }} بیشتر باشد. This value should be greater than or equal to {{ compared_value }}. این مقدار باید بزرگتر یا مساوی با {{ compared_value }} باشد. This value should be identical to {{ compared_value_type }} {{ compared_value }}. این مقدار باید با {{ compared_value_type }} {{ compared_value }} یکی باشد. This value should be less than {{ compared_value }}. این مقدار باید کمتر از {{ compared_value }} باشد. This value should be less than or equal to {{ compared_value }}. این مقدار باید کمتر یا مساوی با {{ compared_value }} باشد. This value should not be equal to {{ compared_value }}. این مقدار نباید با {{ compared_value }} برابر باشد. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. این مقدار نباید {{ compared_value_type }} {{ compared_value }} یکی باشد. PK]@T\442Validator/Resources/translations/validators.af.xlfnu[ This value should be false. Hierdie waarde moet vals wees. This value should be true. Hierdie waarde moet waar wees. This value should be of type {{ type }}. Hierdie waarde moet van die soort {{type}} wees. This value should be blank. Hierdie waarde moet leeg wees. The value you selected is not a valid choice. Die waarde wat jy gekies het is nie 'n geldige keuse nie. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Jy moet ten minste {{ limit }} kies.|Jy moet ten minste {{ limit }} keuses kies. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Jy moet by die meeste {{ limit }} keuse kies.|Jy moet by die meeste {{ limit }} keuses kies. One or more of the given values is invalid. Een of meer van die gegewe waardes is ongeldig. The fields {{ fields }} were not expected. Die velde {{ fields }} is nie verwag nie. The fields {{ fields }} are missing. Die velde {{ fields }} ontbreek. This value is not a valid date. Hierdie waarde is nie 'n geldige datum nie. This value is not a valid datetime. Hierdie waarde is nie 'n geldige datum en tyd nie. This value is not a valid email address. Hierdie waarde is nie 'n geldige e-pos adres nie. The file could not be found. Die lêer kon nie gevind word nie. The file is not readable. Die lêer kan nie gelees word nie. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Die lêer is te groot ({{ size }} {{ suffix }}). Toegelaat maksimum grootte is {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Die MIME-tipe van die lêer is ongeldig ({{ type }}). Toegelaat MIME-tipes is {{ types }}. This value should be {{ limit }} or less. Hierdie waarde moet {{ limit }} of minder wees. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Hierdie waarde is te lank. Dit moet {{ limit }} karakter of minder wees.|Hierdie waarde is te lank. Dit moet {{ limit }} karakters of minder wees. This value should be {{ limit }} or more. Hierdie waarde moet {{ limit }} of meer wees. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Hierdie waarde is te kort. Dit moet {{ limit }} karakter of meer wees.|Hierdie waarde is te kort. Dit moet {{ limit }} karakters of meer wees. This value should not be blank. Hierdie waarde moet nie leeg wees nie. This value should not be null. Hierdie waarde moet nie nul wees nie. This value should be null. Hierdie waarde moet nul wees. This value is not valid. Hierdie waarde is nie geldig nie. This value is not a valid time. Hierdie waarde is nie 'n geldige tyd nie. This value is not a valid URL. Hierdie waarde is nie 'n geldige URL nie. The two values should be equal. Die twee waardes moet gelyk wees. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Die lêer is te groot. Toegelaat maksimum grootte is {{ limit }} {{ suffix }}. The file is too large. Die lêer is te groot. The file could not be uploaded. Die lêer kan nie opgelaai word nie. This value should be a valid number. Hierdie waarde moet 'n geldige nommer wees. This file is not a valid image. Hierdie lêer is nie 'n geldige beeld nie. This is not a valid IP address. Hierdie is nie 'n geldige IP-adres nie. This value is not a valid language. Hierdie waarde is nie 'n geldige taal nie. This value is not a valid locale. Hierdie waarde is nie 'n geldige land instelling nie. This value is not a valid country. Hierdie waarde is nie 'n geldige land nie. This value is already used. Hierdie waarde word reeds gebruik. The size of the image could not be detected. Die grootte van die beeld kon nie opgespoor word nie. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Die beeld breedte is te groot ({{ width }}px). Toegelaat maksimum breedte is {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Die beeld breedte is te klein ({{ width }}px). Minimum breedte verwag is {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Die beeld hoogte is te groot ({{ height }}px). Toegelaat maksimum hoogte is {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Die beeld hoogte is te klein ({{ height }}px). Minimum hoogte verwag is {{ min_height }}px. This value should be the user current password. Hierdie waarde moet die huidige wagwoord van die gebruiker wees. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Hierdie waarde moet presies {{ limit }} karakter wees.|Hierdie waarde moet presies {{ limit }} karakters wees. The file was only partially uploaded. Die lêer is slegs gedeeltelik opgelaai. No file was uploaded. Geen lêer is opgelaai nie. No temporary folder was configured in php.ini. Geen tydelike lêer is ingestel in php.ini nie. Cannot write temporary file to disk. Kan nie tydelike lêer skryf op skyf nie. A PHP extension caused the upload to fail. 'n PHP-uitbreiding veroorsaak die oplaai van die lêer om te misluk. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Hierdie versameling moet {{ limit }} element of meer bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Hierdie versameling moet {{ limit }} element of minder bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Hierdie versameling moet presies {{ limit }} element bevat.|Hierdie versameling moet presies {{ limit }} elemente bevat. Invalid card number. Ongeldige kredietkaart nommer. Unsupported card type or invalid card number. Nie-ondersteunde tipe kaart of ongeldige kredietkaart nommer. PK]˺Q1Q12Validator/Resources/translations/validators.tr.xlfnu[ This value should be false. Bu değer olumsuz olmalıdır. This value should be true. Bu değer olumlu olmalıdır. This value should be of type {{ type }}. Bu değerin tipi {{ type }} olmalıdır. This value should be blank. Bu değer boş olmalıdır. The value you selected is not a valid choice. Seçtiğiniz değer geçerli bir seçenek değil. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. En az {{ limit }} seçenek belirtmelisiniz. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. En çok {{ limit }} seçenek belirtmelisiniz. One or more of the given values is invalid. Verilen değerlerden bir veya daha fazlası geçersiz. The fields {{ fields }} were not expected. {{ fields }} alanları kabul edilmedi. The fields {{ fields }} are missing. {{ fields }} alanları eksik. This value is not a valid date. Bu değer doğru bir tarih biçimi değildir. This value is not a valid datetime. Bu değer doğru bir tarihsaat biçimi değildir. This value is not a valid email address. Bu değer doğru bir e-mail adresi değildir. The file could not be found. Dosya bulunamadı. The file is not readable. Dosya okunabilir değil. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Dosya çok büyük ({{ size }} {{ suffix }}). İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Dosyanın mime tipi geçersiz ({{ type }}). İzin verilen mime tipleri {{ types }}. This value should be {{ limit }} or less. Bu değer {{ limit }} ve altında olmalıdır. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Bu değer çok uzun. {{ limit }} karakter veya daha az olmalıdır. This value should be {{ limit }} or more. Bu değer {{ limit }} veya daha fazla olmalıdır. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Bu değer çok kısa. {{ limit }} karakter veya daha fazla olmaldır. This value should not be blank. Bu değer boşluk olamaz. This value should not be null. Bu değer boş bırakılmamalıdır. This value should be null. Bu değer boş bırakılmalıdır. This value is not valid. Bu değer geçerli değil. This value is not a valid time. Bu değer doğru bir saat değil. This value is not a valid URL. Bu değer doğru bir URL değil. The two values should be equal. İki değer eşit olmalıdır. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Dosya çok büyük. İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}. The file is too large. Dosya çok büyük. The file could not be uploaded. Dosya yüklenemiyor. This value should be a valid number. Bu değer geçerli bir rakam olmalıdır. This file is not a valid image. Bu dosya geçerli bir resim değildir. This is not a valid IP address. Bu geçerli bir IP adresi değildir. This value is not a valid language. Bu değer geçerli bir lisan değil. This value is not a valid locale. Bu değer geçerli bir yer değildir. This value is not a valid country. Bu değer geçerli bir ülke değildir. This value is already used. Bu değer şu anda kullanımda. The size of the image could not be detected. Resmin boyutu saptanamıyor. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Resmin genişliği çok büyük ({{ width }}px). İzin verilen en büyük genişlik {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Resmin genişliği çok küçük ({{ width }}px). En az {{ min_width }}px olmalıdır. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Resmin yüksekliği çok büyük ({{ height }}px). İzin verilen en büyük yükseklik {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Resmin yüksekliği çok küçük ({{ height }}px). En az {{ min_height }}px olmalıdır. This value should be the user current password. Bu değer kullanıcının şu anki şifresi olmalıdır. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Bu değer tam olarak {{ limit }} karakter olmaldır. The file was only partially uploaded. Dosya sadece kısmen yüklendi. No file was uploaded. Hiçbir dosya yüklenmedi. No temporary folder was configured in php.ini. php.ini içerisinde geçici dizin tanımlanmadı. Cannot write temporary file to disk. Geçici dosya diske yazılamıyor. A PHP extension caused the upload to fail. Bir PHP eklentisi dosyanın yüklemesini başarısız kıldı. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Bu derlem {{ limit }} veya daha çok eleman içermelidir. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Bu derlem {{ limit }} veya daha az eleman içermelidir. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Bu derlem {{ limit }} eleman içermelidir. Invalid card number. Geçersiz kart numarası. Unsupported card type or invalid card number. Desteklenmeyen kart tipi veya geçersiz kart numarası. PK]1^447Validator/Resources/translations/validators.sr_Latn.xlfnu[ This value should be false. Vrednost treba da bude netačna. This value should be true. Vrednost treba da bude tačna. This value should be of type {{ type }}. Vrednost treba da bude tipa {{ type }}. This value should be blank. Vrednost treba da bude prazna. The value you selected is not a valid choice. Vrednost treba da bude jedna od ponuđenih. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Izaberite bar {{ limit }} mogućnost.|Izaberite bar {{ limit }} mogućnosti.|Izaberite bar {{ limit }} mogućnosti. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Izaberite najviše {{ limit }} mogućnost.|Izaberite najviše {{ limit }} mogućnosti.|Izaberite najviše {{ limit }} mogućnosti. One or more of the given values is invalid. Jedna ili više vrednosti je nevalidna. The fields {{ fields }} were not expected. Polja {{ fields }} nisu bila očekivana. The fields {{ fields }} are missing. Polja {{ fields }} nedostaju. This value is not a valid date. Vrednost nije validan datum. This value is not a valid datetime. Vrednost nije validan datum-vreme. This value is not a valid email address. Vrednost nije validna adresa elektronske pošte. The file could not be found. Datoteka ne može biti pronađena. The file is not readable. Datoteka nije čitljiva. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime tip datoteke nije validan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}. This value should be {{ limit }} or less. Vrednost treba da bude {{ limit }} ili manje. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Vrednost je predugačka. Treba da ima {{ limit }} karakter ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje. This value should be {{ limit }} or more. Vrednost treba da bude {{ limit }} ili više. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Vrednost je prekratka. Treba da ima {{ limit }} karakter ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više. This value should not be blank. Vrednost ne treba da bude prazna. This value should not be null. Vrednost ne treba da bude null. This value should be null. Vrednost treba da bude null. This value is not valid. Vrednost je nevalidna. This value is not a valid time. Vrednost nije validno vreme. This value is not a valid URL. Vrednost nije validan URL. The two values should be equal. Obe vrednosti treba da budu jednake. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The file is too large. Datoteka je prevelika. The file could not be uploaded. Datoteka ne može biti otpremljena. This value should be a valid number. Vrednost treba da bude validan broj. This file is not a valid image. Ova datoteka nije validna slika. This is not a valid IP address. Ovo nije validna IP adresa. This value is not a valid language. Vrednost nije validan jezik. This value is not a valid locale. Vrednost nije validan lokal. This value is not a valid country. Vrednost nije validna zemlja. This value is already used. Vrednost je već iskorišćena. The size of the image could not be detected. Veličina slike ne može biti određena. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Širina slike je prevelika ({{ width }}px). Najeća dozvoljena širina je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Visina slike je prevelika ({{ height }}px). Najeća dozvoljena visina je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px. This value should be the user current password. Vrednost treba da bude trenutna korisnička lozinka. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Vrednost treba da ima tačno {{ limit }} karakter.|Vrednost treba da ima tačno {{ limit }} karaktera.|Vrednost treba da ima tačno {{ limit }} karaktera. The file was only partially uploaded. Datoteka je samo parcijalno otpremljena. No file was uploaded. Datoteka nije otpremljena. No temporary folder was configured in php.ini. Privremeni direktorijum nije konfigurisan u php.ini. Cannot write temporary file to disk. Nemoguće pisanje privremene datoteke na disk. A PHP extension caused the upload to fail. PHP ekstenzija je prouzrokovala neuspeh otpremanja datoteke. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ova kolekcija treba da sadrži tačno {{ limit }} element.|Ova kolekcija treba da sadrži tačno {{ limit }} elementa.|Ova kolekcija treba da sadrži tačno {{ limit }} elemenata. Invalid card number. Nevalidan broj kartice. Unsupported card type or invalid card number. Nevalidan broj kartice ili tip kartice nije podržan. PK]\,yzz-Validator/Constraints/Collection/Required.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Required as BaseRequired; /** * @Annotation * * @author Bernhard Schussek * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Validator\Constraints\Required} instead. */ class Required extends BaseRequired { } PK]خ zz-Validator/Constraints/Collection/Optional.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Optional as BaseOptional; /** * @Annotation * * @author Bernhard Schussek * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Validator\Constraints\Optional} instead. */ class Optional extends BaseOptional { } PK]dXBBValidator/Constraints/Issn.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Antonio J. García Lagar */ class Issn extends Constraint { public $message = 'This value is not a valid ISSN.'; public $caseSensitive = false; public $requireHyphen = false; } PK]oo(Validator/Constraints/RangeValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek */ class RangeValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (!is_numeric($value)) { $this->context->addViolation($constraint->invalidMessage, array( '{{ value }}' => $value, )); return; } if (null !== $constraint->max && $value > $constraint->max) { $this->context->addViolation($constraint->maxMessage, array( '{{ value }}' => $value, '{{ limit }}' => $constraint->max, )); return; } if (null !== $constraint->min && $value < $constraint->min) { $this->context->addViolation($constraint->minMessage, array( '{{ value }}' => $value, '{{ limit }}' => $constraint->min, )); } } } PK]S탟Validator/Constraints/Date.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Date extends Constraint { public $message = 'This value is not a valid date.'; } PK]cy  "Validator/Constraints/DateTime.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class DateTime extends Constraint { public $message = 'This value is not a valid datetime.'; } PK]NH"Validator/Constraints/LessThan.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class LessThan extends AbstractComparison { public $message = 'This value should be less than {{ compared_value }}.'; } PK]mԼ\\1Validator/Constraints/NotIdenticalToValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values aren't identical (!==). * * @author Daniel Holmes */ class NotIdenticalToValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 !== $value2; } } PK]('Validator/Constraints/TimeValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class TimeValidator extends ConstraintValidator { const PATTERN = '/^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/'; /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value || $value instanceof \DateTime) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if (!preg_match(static::PATTERN, $value)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK]I7UValidator/Constraints/False.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class False extends Constraint { public $message = 'This value should be false.'; } PK]V`'Validator/Constraints/IbanValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Manuel Reinhard * @author Michael Schummel * @link http://www.michael-schummel.de/2007/10/05/iban-prufung-mit-php/ */ class IbanValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } // An IBAN without a country code is not an IBAN. if (0 === preg_match('/[A-Z]/', $value)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); return; } $teststring = preg_replace('/\s+/', '', $value); if (strlen($teststring) < 4) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); return; } $teststring = substr($teststring, 4) .strval(ord($teststring{0}) - 55) .strval(ord($teststring{1}) - 55) .substr($teststring, 2, 2); $teststring = preg_replace_callback('/[A-Z]/', function ($letter) { return intval(ord(strtolower($letter[0])) - 87); }, $teststring); $rest = 0; $strlen = strlen($teststring); for ($pos = 0; $pos < $strlen; $pos += 7) { $part = strval($rest).substr($teststring, $pos, 7); $rest = intval($part) % 97; } if ($rest != 1) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); return; } } } PK]BBValidator/Constraints/Range.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Range extends Constraint { public $minMessage = 'This value should be {{ limit }} or more.'; public $maxMessage = 'This value should be {{ limit }} or less.'; public $invalidMessage = 'This value should be a valid number.'; public $min; public $max; public function __construct($options = null) { parent::__construct($options); if (null === $this->min && null === $this->max) { throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max')); } } } PK]|4XX&Validator/Constraints/UrlValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class UrlValidator extends ConstraintValidator { const PATTERN = '~^ (%s):// # protocol ( ([\pL\pN\pS-]+\.)+([\pL]|xn\-\-[\pL\pN-]+)+ # a domain name | # or \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # a IP address | # or \[ (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::)))) \] # a IPv6 address ) (:[0-9]+)? # a port (optional) (/?|/\S+) # a /, nothing or a / with something $~ixu'; /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $pattern = sprintf(static::PATTERN, implode('|', $constraint->protocols)); if (!preg_match($pattern, $value)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK][A)Validator/Constraints/LessThanOrEqual.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class LessThanOrEqual extends AbstractComparison { public $message = 'This value should be less than or equal to {{ compared_value }}.'; } PK]Hð Validator/Constraints/Locale.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Locale extends Constraint { public $message = 'This value is not a valid locale.'; } PK]cValidator/Constraints/Ip.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Constraint; /** * Validates that a value is a valid IP address * * @Annotation * * @author Bernhard Schussek * @author Joseph Bielawski * * @api */ class Ip extends Constraint { const V4 = '4'; const V6 = '6'; const ALL = 'all'; // adds FILTER_FLAG_NO_PRIV_RANGE flag (skip private ranges) const V4_NO_PRIV = '4_no_priv'; const V6_NO_PRIV = '6_no_priv'; const ALL_NO_PRIV = 'all_no_priv'; // adds FILTER_FLAG_NO_RES_RANGE flag (skip reserved ranges) const V4_NO_RES = '4_no_res'; const V6_NO_RES = '6_no_res'; const ALL_NO_RES = 'all_no_res'; // adds FILTER_FLAG_NO_PRIV_RANGE and FILTER_FLAG_NO_RES_RANGE flags (skip both) const V4_ONLY_PUBLIC = '4_public'; const V6_ONLY_PUBLIC = '6_public'; const ALL_ONLY_PUBLIC = 'all_public'; protected static $versions = array( self::V4, self::V6, self::ALL, self::V4_NO_PRIV, self::V6_NO_PRIV, self::ALL_NO_PRIV, self::V4_NO_RES, self::V6_NO_RES, self::ALL_NO_RES, self::V4_ONLY_PUBLIC, self::V6_ONLY_PUBLIC, self::ALL_ONLY_PUBLIC, ); public $version = self::V4; public $message = 'This is not a valid IP address.'; /** * {@inheritDoc} */ public function __construct($options = null) { parent::__construct($options); if (!in_array($this->version, self::$versions)) { throw new ConstraintDefinitionException(sprintf('The option "version" must be one of "%s"', implode('", "', self::$versions))); } } } PK],,Validator/Constraints/Isbn.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @Annotation * * @author The Whole Life To Learn */ class Isbn extends Constraint { public $isbn10Message = 'This value is not a valid ISBN-10.'; public $isbn13Message = 'This value is not a valid ISBN-13.'; public $bothIsbnMessage = 'This value is neither a valid ISBN-10 nor a valid ISBN-13.'; public $isbn10; public $isbn13; public function __construct($options = null) { if (null !== $options && !is_array($options)) { $options = array( 'isbn10' => $options, 'isbn13' => $options, ); } parent::__construct($options); if (null === $this->isbn10 && null === $this->isbn13) { throw new MissingOptionsException(sprintf('Either option "isbn10" or "isbn13" must be given for constraint "%s".', __CLASS__), array('isbn10', 'isbn13')); } } } PK]?5Validator/Constraints/AbstractComparisonValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * Provides a base class for the validation of property comparisons. * * @author Daniel Holmes */ abstract class AbstractComparisonValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (!$this->compareValues($value, $constraint->value)) { $this->context->addViolation($constraint->message, array( '{{ value }}' => $this->valueToString($constraint->value), '{{ compared_value }}' => $this->valueToString($constraint->value), '{{ compared_value_type }}' => $this->valueToType($constraint->value) )); } } /** * Returns a string representation of the type of the value. * * @param mixed $value * * @return string */ private function valueToType($value) { return is_object($value) ? get_class($value) : gettype($value); } /** * Returns a string representation of the value. * * @param mixed $value * * @return string */ private function valueToString($value) { if (is_object($value) && method_exists($value, '__toString')) { return (string) $value; } if ($value instanceof \DateTime) { return $value->format('Y-m-d H:i:s'); } return var_export($value, true); } /** * Compares the two given values to find if their relationship is valid * * @param mixed $value1 The first value to compare * @param mixed $value2 The second value to compare * * @return Boolean true if the relationship is valid, false otherwise */ abstract protected function compareValues($value1, $value2); } PK](.ww5Validator/Constraints/GreaterThanOrEqualValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are greater than or equal to the previous (>=). * * @author Daniel Holmes */ class GreaterThanOrEqualValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 >= $value2; } } PK]> i//#Validator/Constraints/Existence.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @author Bernhard Schussek */ abstract class Existence extends Constraint { public $constraints = array(); public function getDefaultOption() { return 'constraints'; } } PK]<8S(Validator/Constraints/ImageValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Validates whether a value is a valid image file and is valid * against minWidth, maxWidth, minHeight and maxHeight constraints * * @author Benjamin Dulau */ class ImageValidator extends FileValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { $violations = count($this->context->getViolations()); parent::validate($value, $constraint); $failed = count($this->context->getViolations()) !== $violations; if ($failed || null === $value || '' === $value) { return; } if (null === $constraint->minWidth && null === $constraint->maxWidth && null === $constraint->minHeight && null === $constraint->maxHeight && null === $constraint->minRatio && null === $constraint->maxRatio && $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait) { return; } $size = @getimagesize($value); if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) { $this->context->addViolation($constraint->sizeNotDetectedMessage); return; } $width = $size[0]; $height = $size[1]; if ($constraint->minWidth) { if (!ctype_digit((string) $constraint->minWidth)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum width', $constraint->minWidth)); } if ($width < $constraint->minWidth) { $this->context->addViolation($constraint->minWidthMessage, array( '{{ width }}' => $width, '{{ min_width }}' => $constraint->minWidth )); return; } } if ($constraint->maxWidth) { if (!ctype_digit((string) $constraint->maxWidth)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum width', $constraint->maxWidth)); } if ($width > $constraint->maxWidth) { $this->context->addViolation($constraint->maxWidthMessage, array( '{{ width }}' => $width, '{{ max_width }}' => $constraint->maxWidth )); return; } } if ($constraint->minHeight) { if (!ctype_digit((string) $constraint->minHeight)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum height', $constraint->minHeight)); } if ($height < $constraint->minHeight) { $this->context->addViolation($constraint->minHeightMessage, array( '{{ height }}' => $height, '{{ min_height }}' => $constraint->minHeight )); return; } } if ($constraint->maxHeight) { if (!ctype_digit((string) $constraint->maxHeight)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum height', $constraint->maxHeight)); } if ($height > $constraint->maxHeight) { $this->context->addViolation($constraint->maxHeightMessage, array( '{{ height }}' => $height, '{{ max_height }}' => $constraint->maxHeight )); } } $ratio = $width / $height; if (null !== $constraint->minRatio) { if (!is_numeric((string) $constraint->minRatio)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum ratio', $constraint->minRatio)); } if ($ratio < $constraint->minRatio) { $this->context->addViolation($constraint->minRatioMessage, array( '{{ ratio }}' => $ratio, '{{ min_ratio }}' => $constraint->minRatio )); } } if (null !== $constraint->maxRatio) { if (!is_numeric((string) $constraint->maxRatio)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum ratio', $constraint->maxRatio)); } if ($ratio > $constraint->maxRatio) { $this->context->addViolation($constraint->maxRatioMessage, array( '{{ ratio }}' => $ratio, '{{ max_ratio }}' => $constraint->maxRatio )); } } if (!$constraint->allowSquare && $width == $height) { $this->context->addViolation($constraint->allowSquareMessage, array( '{{ width }}' => $width, '{{ height }}' => $height )); } if (!$constraint->allowLandscape && $width > $height) { $this->context->addViolation($constraint->allowLandscapeMessage, array( '{{ width }}' => $width, '{{ height }}' => $height )); } if (!$constraint->allowPortrait && $width < $height) { $this->context->addViolation($constraint->allowPortraitMessage, array( '{{ width }}' => $width, '{{ height }}' => $height )); } } } PK]D*Validator/Constraints/NotNullValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class NotNullValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { $this->context->addViolation($constraint->message); } } } PK]m\\,Validator/Constraints/AbstractComparison.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Used for the comparison of values. * * @author Daniel Holmes */ abstract class AbstractComparison extends Constraint { public $message; public $value; /** * {@inheritDoc} */ public function __construct($options = null) { if (is_array($options) && !isset($options['value'])) { throw new ConstraintDefinitionException(sprintf( 'The %s constraint requires the "value" option to be set.', get_class($this) )); } parent::__construct($options); } /** * {@inheritDoc} */ public function getDefaultOption() { return 'value'; } } PK]\\+Validator/Constraints/LessThanValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are less than the previous (<). * * @author Daniel Holmes */ class LessThanValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 < $value2; } } PK]e8B $Validator/Constraints/Collection.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Collection extends Constraint { public $fields = array(); public $allowExtraFields = false; public $allowMissingFields = false; public $extraFieldsMessage = 'This field was not expected.'; public $missingFieldsMessage = 'This field is missing.'; /** * {@inheritDoc} */ public function __construct($options = null) { // no known options set? $options is the fields array if (is_array($options) && !array_intersect(array_keys($options), array('groups', 'fields', 'allowExtraFields', 'allowMissingFields', 'extraFieldsMessage', 'missingFieldsMessage'))) { $options = array('fields' => $options); } parent::__construct($options); if (!is_array($this->fields)) { throw new ConstraintDefinitionException(sprintf('The option "fields" is expected to be an array in constraint %s', __CLASS__)); } foreach ($this->fields as $fieldName => $field) { // the XmlFileLoader and YamlFileLoader pass the field Optional // and Required constraint as an array with exactly one element if (is_array($field) && count($field) == 1) { $this->fields[$fieldName] = $field = $field[0]; } if (!$field instanceof Optional && !$field instanceof Required) { $this->fields[$fieldName] = $field = new Required($field); } if (!is_array($field->constraints)) { $field->constraints = array($field->constraints); } foreach ($field->constraints as $constraint) { if (!$constraint instanceof Constraint) { throw new ConstraintDefinitionException(sprintf('The value %s of the field %s is not an instance of Constraint in constraint %s', $constraint, $fieldName, __CLASS__)); } if ($constraint instanceof Valid) { throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', __CLASS__)); } } } } public function getRequiredOptions() { return array('fields'); } } PK]}a%Validator/Constraints/GreaterThan.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class GreaterThan extends AbstractComparison { public $message = 'This value should be greater than {{ compared_value }}.'; } PK]~%ɋValidator/Constraints/Valid.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Valid extends Constraint { public $traverse = true; public $deep = false; public function __construct($options = null) { if (is_array($options) && array_key_exists('groups', $options)) { throw new ConstraintDefinitionException(sprintf('The option "groups" is not supported by the constraint %s', __CLASS__)); } parent::__construct($options); } } PK]F'Validator/Constraints/TypeValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class TypeValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } $type = strtolower($constraint->type); $type = $type == 'boolean' ? 'bool' : $constraint->type; $isFunction = 'is_'.$type; $ctypeFunction = 'ctype_'.$type; if (function_exists($isFunction) && call_user_func($isFunction, $value)) { return; } elseif (function_exists($ctypeFunction) && call_user_func($ctypeFunction, $value)) { return; } elseif ($value instanceof $constraint->type) { return; } $this->context->addViolation($constraint->message, array( '{{ value }}' => is_object($value) ? get_class($value) : (is_array($value) ? 'Array' : (string) $value), '{{ type }}' => $constraint->type, )); } } PK]̋ Validator/Constraints/Regex.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Regex extends Constraint { public $message = 'This value is not valid.'; public $pattern; public $htmlPattern = null; public $match = true; /** * {@inheritDoc} */ public function getDefaultOption() { return 'pattern'; } /** * {@inheritDoc} */ public function getRequiredOptions() { return array('pattern'); } /** * Returns htmlPattern if exists or pattern is convertible. * * @return string|null */ public function getHtmlPattern() { // If htmlPattern is specified, use it if (null !== $this->htmlPattern) { return empty($this->htmlPattern) ? null : $this->htmlPattern; } return $this->getNonDelimitedPattern(); } /** * Converts the htmlPattern to a suitable format for HTML5 pattern. * Example: /^[a-z]+$/ would be converted to [a-z]+ * However, if options are specified, it cannot be converted * * Pattern is also ignored if match=false since the pattern should * then be reversed before application. * * @todo reverse pattern in case match=false as per issue #5307 * * @link http://dev.w3.org/html5/spec/single-page.html#the-pattern-attribute * * @return string|null */ private function getNonDelimitedPattern() { // If match = false, pattern should not be added to HTML5 validation if (!$this->match) { return null; } if (preg_match('/^(.)(\^?)(.*?)(\$?)\1$/', $this->pattern, $matches)) { $delimiter = $matches[1]; $start = empty($matches[2]) ? '.*' : ''; $pattern = $matches[3]; $end = empty($matches[4]) ? '.*' : ''; // Unescape the delimiter in pattern $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern); return $start.$pattern.$end; } return null; } } PK]EW^*Validator/Constraints/CountryValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid country code * * @author Bernhard Schussek * * @api */ class CountryValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $countries = Intl::getRegionBundle()->getCountryNames(); if (!isset($countries[$value])) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK] 00Validator/Constraints/Url.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Url extends Constraint { public $message = 'This value is not a valid URL.'; public $protocols = array('http', 'https'); } PK]Q,Validator/Constraints/GreaterThanOrEqual.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class GreaterThanOrEqual extends AbstractComparison { public $message = 'This value should be greater than or equal to {{ compared_value }}.'; } PK]zet -Validator/Constraints/ExpressionValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\Validator\Exception\RuntimeException; /** * @author Fabien Potencier * @author Bernhard Schussek */ class ExpressionValidator extends ConstraintValidator { /** * @var PropertyAccessorInterface */ private $propertyAccessor; /** * @var ExpressionLanguage */ private $expressionLanguage; public function __construct(PropertyAccessorInterface $propertyAccessor) { $this->propertyAccessor = $propertyAccessor; } /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } $variables = array(); if (null === $this->context->getPropertyName()) { $variables['this'] = $value; } else { // Extract the object that the property belongs to from the object // graph $path = new PropertyPath($this->context->getPropertyPath()); $parentPath = $path->getParent(); $root = $this->context->getRoot(); $variables['value'] = $value; $variables['this'] = $parentPath ? $this->propertyAccessor->getValue($root, $parentPath) : $root; } if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) { $this->context->addViolation($constraint->message); } } private function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(); } return $this->expressionLanguage; } } PK]x.`ss"Validator/Constraints/Callback.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Callback extends Constraint { /** * @var string|callable * * @since 2.4 */ public $callback; /** * @var array * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. */ public $methods; /** * {@inheritdoc} */ public function __construct($options = null) { // Invocation through annotations with an array parameter only if (is_array($options) && 1 === count($options) && isset($options['value'])) { $options = $options['value']; } if (is_array($options) && !isset($options['callback']) && !isset($options['methods']) && !isset($options['groups'])) { if (is_callable($options)) { $options = array('callback' => $options); } else { // BC with Symfony < 2.4 $options = array('methods' => $options); } } parent::__construct($options); } /** * {@inheritdoc} */ public function getDefaultOption() { return 'callback'; } /** * {@inheritdoc} */ public function getTargets() { return self::CLASS_CONSTRAINT; } } PK]tUה"Validator/Constraints/Required.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Bernhard Schussek */ class Required extends Existence { } PK]rs+"Validator/Constraints/Optional.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Bernhard Schussek */ class Optional extends Existence { } PK]"-Validator/Constraints/CardSchemeValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * Validates that a card number belongs to a specified scheme. * * @see http://en.wikipedia.org/wiki/Bank_card_number * @see http://www.regular-expressions.info/creditcard.html * @author Tim Nagel */ class CardSchemeValidator extends ConstraintValidator { protected $schemes = array( /** * American Express card numbers start with 34 or 37 and have 15 digits. */ 'AMEX' => array( '/^3[47][0-9]{13}$/' ), /** * China UnionPay cards start with 62 and have between 16 and 19 digits. * Please note that these cards do not follow Luhn Algorithm as a checksum. */ 'CHINA_UNIONPAY' => array( '/^62[0-9]{14,17}$/' ), /** * Diners Club card numbers begin with 300 through 305, 36 or 38. All have 14 digits. * There are Diners Club cards that begin with 5 and have 16 digits. * These are a joint venture between Diners Club and MasterCard, and should be processed like a MasterCard. */ 'DINERS' => array( '/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/', ), /** * Discover card numbers begin with 6011, 622126 through 622925, 644 through 649 or 65. * All have 16 digits */ 'DISCOVER' => array( '/^6011[0-9]{12}$/', '/^64[4-9][0-9]{13}$/', '/^65[0-9]{14}$/', '/^622(12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|91[0-9]|92[0-5])[0-9]{10}$/' ), /** * InstaPayment cards begin with 637 through 639 and have 16 digits */ 'INSTAPAYMENT' => array( '/^63[7-9][0-9]{13}$/' ), /** * JCB cards beginning with 2131 or 1800 have 15 digits. * JCB cards beginning with 35 have 16 digits. */ 'JCB' => array( '/^(?:2131|1800|35[0-9]{3})[0-9]{11}$/' ), /** * Laser cards begin with either 6304, 6706, 6709 or 6771 and have between 16 and 19 digits */ 'LASER' => array( '/^(6304|670[69]|6771)[0-9]{12,15}$/' ), /** * Maestro cards begin with either 5018, 5020, 5038, 5893, 6304, 6759, 6761, 6762, 6763 or 0604 * They have between 12 and 19 digits */ 'MAESTRO' => array( '/^(5018|5020|5038|6304|6759|6761|676[23]|0604)[0-9]{8,15}$/' ), /** * All MasterCard numbers start with the numbers 51 through 55. All have 16 digits. */ 'MASTERCARD' => array( '/^5[1-5][0-9]{14}$/' ), /** * All Visa card numbers start with a 4. New cards have 16 digits. Old cards have 13. */ 'VISA' => array( '/^4([0-9]{12}|[0-9]{15})$/' ), ); /** * Validates a creditcard belongs to a specified scheme. * * @param mixed $value * @param Constraint $constraint */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_numeric($value)) { $this->context->addViolation($constraint->message); return; } $schemes = array_flip((array) $constraint->schemes); $schemeRegexes = array_intersect_key($this->schemes, $schemes); foreach ($schemeRegexes as $regexes) { foreach ($regexes as $regex) { if (preg_match($regex, $value)) { return; } } } $this->context->addViolation($constraint->message); } } PK] n-Validator/Constraints/CollectionValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class CollectionValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (!is_array($value) && !($value instanceof \Traversable && $value instanceof \ArrayAccess)) { throw new UnexpectedTypeException($value, 'array or Traversable and ArrayAccess'); } $group = $this->context->getGroup(); foreach ($constraint->fields as $field => $fieldConstraint) { if ( // bug fix issue #2779 (is_array($value) && array_key_exists($field, $value)) || ($value instanceof \ArrayAccess && $value->offsetExists($field)) ) { foreach ($fieldConstraint->constraints as $constr) { $this->context->validateValue($value[$field], $constr, '['.$field.']', $group); } } elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) { $this->context->addViolationAt('['.$field.']', $constraint->missingFieldsMessage, array( '{{ field }}' => $field ), null); } } if (!$constraint->allowExtraFields) { foreach ($value as $field => $fieldValue) { if (!isset($constraint->fields[$field])) { $this->context->addViolationAt('['.$field.']', $constraint->extraFieldsMessage, array( '{{ field }}' => $field ), $fieldValue); } } } } } PK]}&& Validator/Constraints/Length.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Length extends Constraint { public $maxMessage = 'This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.'; public $minMessage = 'This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.'; public $exactMessage = 'This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.'; public $max; public $min; public $charset = 'UTF-8'; public function __construct($options = null) { if (null !== $options && !is_array($options)) { $options = array( 'min' => $options, 'max' => $options, ); } parent::__construct($options); if (null === $this->min && null === $this->max) { throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max')); } } } PK]7Validator/Constraints/Time.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Time extends Constraint { public $message = 'This value is not a valid time.'; } PK]44'Validator/Constraints/IssnValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether the value is a valid ISSN. * * @author Antonio J. García Lagar * * @see https://en.wikipedia.org/wiki/Issn */ class IssnValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } // Compose regex pattern $digitsPattern = $constraint->requireHyphen ? '\d{4}-\d{3}' : '\d{4}-?\d{3}'; $checksumPattern = $constraint->caseSensitive ? '[\d|X]' : '[\d|X|x]'; $pattern = "/^".$digitsPattern.$checksumPattern."$/"; if (!preg_match($pattern, $value)) { $this->context->addViolation($constraint->message); } else { $digits = str_split(strtoupper(str_replace('-', '', $value))); $sum = 0; for ($i = 8; $i > 1; $i--) { $sum += $i * (int) array_shift($digits); } $checksum = 'X' == reset($digits) ? 10 : (int) reset($digits); if (0 != ($sum + $checksum) % 11) { $this->context->addViolation($constraint->message); } } } } PK]SnValidator/Constraints/Null.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Null extends Constraint { public $message = 'This value should be null.'; } PK]Validator/Constraints/All.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class All extends Constraint { public $constraints = array(); /** * {@inheritDoc} */ public function __construct($options = null) { parent::__construct($options); if (!is_array($this->constraints)) { $this->constraints = array($this->constraints); } foreach ($this->constraints as $constraint) { if (!$constraint instanceof Constraint) { throw new ConstraintDefinitionException(sprintf('The value %s is not an instance of Constraint in constraint %s', $constraint, __CLASS__)); } if ($constraint instanceof Valid) { throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', __CLASS__)); } } } public function getDefaultOption() { return 'constraints'; } public function getRequiredOptions() { return array('constraints'); } } PK] * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value match or not given regexp pattern * * @author Bernhard Schussek * @author Joseph Bielawski * * @api */ class RegexValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if ($constraint->match xor preg_match($constraint->pattern, $value)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK]!xHH(Validator/Constraints/CountValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ class CountValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (!is_array($value) && !$value instanceof \Countable) { throw new UnexpectedTypeException($value, 'array or \Countable'); } $count = count($value); if ($constraint->min == $constraint->max && $count != $constraint->min) { $this->context->addViolation($constraint->exactMessage, array( '{{ count }}' => $count, '{{ limit }}' => $constraint->min, ), $value, (int) $constraint->min); return; } if (null !== $constraint->max && $count > $constraint->max) { $this->context->addViolation($constraint->maxMessage, array( '{{ count }}' => $count, '{{ limit }}' => $constraint->max, ), $value, (int) $constraint->max); return; } if (null !== $constraint->min && $count < $constraint->min) { $this->context->addViolation($constraint->minMessage, array( '{{ count }}' => $count, '{{ limit }}' => $constraint->min, ), $value, (int) $constraint->min); } } } PK]e(Validator/Constraints/NotIdenticalTo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class NotIdenticalTo extends AbstractComparison { public $message = 'This value should not be identical to {{ compared_value_type }} {{ compared_value }}.'; } PK]b=n n 'Validator/Constraints/IsbnValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether the value is a valid ISBN-10 or ISBN-13. * * @author The Whole Life To Learn * * @see https://en.wikipedia.org/wiki/Isbn */ class IsbnValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } if (!is_numeric($value)) { $value = str_replace('-', '', $value); } $validation = 0; $value = strtoupper($value); $valueLength = strlen($value); if (10 === $valueLength && null !== $constraint->isbn10) { for ($i = 0; $i < 10; $i++) { if ($value[$i] == 'X') { $validation += 10 * intval(10 - $i); } else { $validation += intval($value[$i]) * intval(10 - $i); } } if ($validation % 11 != 0) { if (null !== $constraint->isbn13) { $this->context->addViolation($constraint->bothIsbnMessage); } else { $this->context->addViolation($constraint->isbn10Message); } } } elseif (13 === $valueLength && null !== $constraint->isbn13) { for ($i = 0; $i < 13; $i += 2) { $validation += intval($value[$i]); } for ($i = 1; $i < 12; $i += 2) { $validation += intval($value[$i]) * 3; } if ($validation % 10 != 0) { if (null !== $constraint->isbn10) { $this->context->addViolation($constraint->bothIsbnMessage); } else { $this->context->addViolation($constraint->isbn13Message); } } } else { if (null !== $constraint->isbn10 && null !== $constraint->isbn13) { $this->context->addViolation($constraint->bothIsbnMessage); } elseif (null !== $constraint->isbn10) { $this->context->addViolation($constraint->isbn10Message); } else { $this->context->addViolation($constraint->isbn13Message); } } } } PK]  "Validator/Constraints/Currency.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Miha Vrhovnik * * @api */ class Currency extends Constraint { public $message = 'This value is not a valid currency.'; } PK]5ʟ'Validator/Constraints/DateValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class DateValidator extends ConstraintValidator { const PATTERN = '/^(\d{4})-(\d{2})-(\d{2})$/'; /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value || $value instanceof \DateTime) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if (!preg_match(static::PATTERN, $value, $matches) || !checkdate($matches[2], $matches[3], $matches[1])) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK]Ǧ!Validator/Constraints/EqualTo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class EqualTo extends AbstractComparison { public $message = 'This value should be equal to {{ compared_value }}.'; } PK] +Validator/Constraints/CallbackValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Validator for Callback constraint * * @author Bernhard Schussek * * @api */ class CallbackValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($object, Constraint $constraint) { if (null === $object) { return; } if (null !== $constraint->callback && null !== $constraint->methods) { throw new ConstraintDefinitionException( 'The Callback constraint supports either the option "callback" ' . 'or "methods", but not both at the same time.' ); } // has to be an array so that we can differentiate between callables // and method names if (null !== $constraint->methods && !is_array($constraint->methods)) { throw new UnexpectedTypeException($constraint->methods, 'array'); } $methods = $constraint->methods ?: array($constraint->callback); foreach ($methods as $method) { if (is_array($method) || $method instanceof \Closure) { if (!is_callable($method)) { throw new ConstraintDefinitionException(sprintf('"%s::%s" targeted by Callback constraint is not a valid callable', $method[0], $method[1])); } call_user_func($method, $object, $this->context); } else { if (!method_exists($object, $method)) { throw new ConstraintDefinitionException(sprintf('Method "%s" targeted by Callback constraint does not exist', $method)); } $reflMethod = new \ReflectionMethod($object, $method); if ($reflMethod->isStatic()) { $reflMethod->invoke(null, $object, $this->context); } else { $reflMethod->invoke($object, $this->context); } } } } } PK]̢VV.Validator/Constraints/IdenticalToValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are identical (===). * * @author Daniel Holmes */ class IdenticalToValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 === $value2; } } PK]`v)Validator/Constraints/LocaleValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid locale code * * @author Bernhard Schussek * * @api */ class LocaleValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $locales = Intl::getLocaleBundle()->getLocaleNames(); if (!isset($locales[$value])) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK]D~SS Validator/Constraints/Choice.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Choice extends Constraint { public $choices; public $callback; public $multiple = false; public $strict = false; public $min = null; public $max = null; public $message = 'The value you selected is not a valid choice.'; public $multipleMessage = 'One or more of the given values is invalid.'; public $minMessage = 'You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.'; public $maxMessage = 'You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.'; /** * {@inheritDoc} */ public function getDefaultOption() { return 'choices'; } } PK]U"Validator/Constraints/NotBlank.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class NotBlank extends Constraint { public $message = 'This value should not be blank.'; } PK]'㔘  %Validator/Constraints/IdenticalTo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class IdenticalTo extends AbstractComparison { public $message = 'This value should be identical to {{ compared_value_type }} {{ compared_value }}.'; } PK]Lֻ$Validator/Constraints/CardScheme.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * Metadata for the CardSchemeValidator. * * @Annotation */ class CardScheme extends Constraint { public $message = 'Unsupported card type or invalid card number.'; public $schemes; public function getDefaultOption() { return 'schemes'; } public function getRequiredOptions() { return array('schemes'); } } PK]ଏ/Validator/Constraints/GroupSequenceProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Annotation to define a group sequence provider * * @Annotation */ class GroupSequenceProvider { } PK]{HHValidator/Constraints/Email.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Email extends Constraint { public $message = 'This value is not a valid email address.'; public $checkMX = false; public $checkHost = false; } PK]+ $Validator/Constraints/NotEqualTo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class NotEqualTo extends AbstractComparison { public $message = 'This value should not be equal to {{ compared_value }}.'; } PK]+Validator/Constraints/DateTimeValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @author Bernhard Schussek * * @api */ class DateTimeValidator extends DateValidator { const PATTERN = '/^(\d{4})-(\d{2})-(\d{2}) (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/'; } PK]vbb.Validator/Constraints/GreaterThanValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are greater than the previous (>). * * @author Daniel Holmes */ class GreaterThanValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 > $value2; } } PK]Ŀ:KK$Validator/Constraints/Expression.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Fabien Potencier * @author Bernhard Schussek */ class Expression extends Constraint { public $message = 'This value is not valid.'; public $expression; /** * {@inheritDoc} */ public function getDefaultOption() { return 'expression'; } /** * {@inheritDoc} */ public function getRequiredOptions() { return array('expression'); } /** * {@inheritDoc} */ public function getTargets() { return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT); } /** * {@inheritDoc} */ public function validatedBy() { return 'validator.expression'; } } PK]&Validator/Constraints/Luhn.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * Metadata for the LuhnValidator. * * @Annotation */ class Luhn extends Constraint { public $message = 'Invalid card number.'; } PK]@vqq'Validator/Constraints/FileValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\HttpFoundation\File\File as FileObject; use Symfony\Component\HttpFoundation\File\UploadedFile; /** * @author Bernhard Schussek * * @api */ class FileValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if ($value instanceof UploadedFile && !$value->isValid()) { switch ($value->getError()) { case UPLOAD_ERR_INI_SIZE: if ($constraint->maxSize) { if (ctype_digit((string) $constraint->maxSize)) { $maxSize = (int) $constraint->maxSize; } elseif (preg_match('/^\d++k$/', $constraint->maxSize)) { $maxSize = $constraint->maxSize * 1024; } elseif (preg_match('/^\d++M$/', $constraint->maxSize)) { $maxSize = $constraint->maxSize * 1048576; } else { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize)); } $maxSize = min(UploadedFile::getMaxFilesize(), $maxSize); } else { $maxSize = UploadedFile::getMaxFilesize(); } $this->context->addViolation($constraint->uploadIniSizeErrorMessage, array( '{{ limit }}' => $maxSize, '{{ suffix }}' => 'bytes', )); return; case UPLOAD_ERR_FORM_SIZE: $this->context->addViolation($constraint->uploadFormSizeErrorMessage); return; case UPLOAD_ERR_PARTIAL: $this->context->addViolation($constraint->uploadPartialErrorMessage); return; case UPLOAD_ERR_NO_FILE: $this->context->addViolation($constraint->uploadNoFileErrorMessage); return; case UPLOAD_ERR_NO_TMP_DIR: $this->context->addViolation($constraint->uploadNoTmpDirErrorMessage); return; case UPLOAD_ERR_CANT_WRITE: $this->context->addViolation($constraint->uploadCantWriteErrorMessage); return; case UPLOAD_ERR_EXTENSION: $this->context->addViolation($constraint->uploadExtensionErrorMessage); return; default: $this->context->addViolation($constraint->uploadErrorMessage); return; } } if (!is_scalar($value) && !$value instanceof FileObject && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $path = $value instanceof FileObject ? $value->getPathname() : (string) $value; if (!is_file($path)) { $this->context->addViolation($constraint->notFoundMessage, array('{{ file }}' => $path)); return; } if (!is_readable($path)) { $this->context->addViolation($constraint->notReadableMessage, array('{{ file }}' => $path)); return; } if ($constraint->maxSize) { if (ctype_digit((string) $constraint->maxSize)) { $size = filesize($path); $limit = (int) $constraint->maxSize; $suffix = 'bytes'; } elseif (preg_match('/^\d++k$/', $constraint->maxSize)) { $size = round(filesize($path) / 1000, 2); $limit = (int) $constraint->maxSize; $suffix = 'kB'; } elseif (preg_match('/^\d++M$/', $constraint->maxSize)) { $size = round(filesize($path) / 1000000, 2); $limit = (int) $constraint->maxSize; $suffix = 'MB'; } else { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize)); } if ($size > $limit) { $this->context->addViolation($constraint->maxSizeMessage, array( '{{ size }}' => $size, '{{ limit }}' => $limit, '{{ suffix }}' => $suffix, '{{ file }}' => $path, )); return; } } if ($constraint->mimeTypes) { if (!$value instanceof FileObject) { $value = new FileObject($value); } $mimeTypes = (array) $constraint->mimeTypes; $mime = $value->getMimeType(); $valid = false; foreach ($mimeTypes as $mimeType) { if ($mimeType === $mime) { $valid = true; break; } if ($discrete = strstr($mimeType, '/*', true)) { if (strstr($mime, '/', true) === $discrete) { $valid = true; break; } } } if (false === $valid) { $this->context->addViolation($constraint->mimeTypesMessage, array( '{{ type }}' => '"'.$mime.'"', '{{ types }}' => '"'.implode('", "', $mimeTypes) .'"', '{{ file }}' => $path, )); } } } } PK]Fn&Validator/Constraints/AllValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class AllValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (!is_array($value) && !$value instanceof \Traversable) { throw new UnexpectedTypeException($value, 'array or Traversable'); } $group = $this->context->getGroup(); foreach ($value as $key => $element) { foreach ($constraint->constraints as $constr) { $this->context->validateValue($element, $constr, '['.$key.']', $group); } } } } PK]{UU-Validator/Constraints/NotEqualToValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are all unequal (!=). * * @author Daniel Holmes */ class NotEqualToValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 != $value2; } } PK]vv'Validator/Constraints/GroupSequence.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Annotation for group sequences * * @Annotation * * @author Bernhard Schussek * * @api */ class GroupSequence { /** * The members of the sequence * @var array */ public $groups; public function __construct(array $groups) { $this->groups = $groups['value']; } } PK]CG^LL*Validator/Constraints/EqualToValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are equal (==). * * @author Daniel Holmes */ class EqualToValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 == $value2; } } PK]0@'Validator/Constraints/NullValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class NullValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null !== $value) { if (is_object($value)) { $value = get_class($value); } elseif (is_array($value)) { $value = 'Array'; } $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK]lValidator/Constraints/Blank.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Blank extends Constraint { public $message = 'This value should be blank.'; } PK]Z+Validator/Constraints/CurrencyValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid currency * * @author Miha Vrhovnik * * @api */ class CurrencyValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $currencies = Intl::getCurrencyBundle()->getCurrencyNames(); if (!isset($currencies[$value])) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK]w!Validator/Constraints/NotNull.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class NotNull extends Constraint { public $message = 'This value should not be null.'; } PK]qp""Validator/Constraints/File.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class File extends Constraint { public $maxSize = null; public $mimeTypes = array(); public $notFoundMessage = 'The file could not be found.'; public $notReadableMessage = 'The file is not readable.'; public $maxSizeMessage = 'The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.'; public $mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.'; public $uploadIniSizeErrorMessage = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.'; public $uploadFormSizeErrorMessage = 'The file is too large.'; public $uploadPartialErrorMessage = 'The file was only partially uploaded.'; public $uploadNoFileErrorMessage = 'No file was uploaded.'; public $uploadNoTmpDirErrorMessage = 'No temporary folder was configured in php.ini.'; public $uploadCantWriteErrorMessage = 'Cannot write temporary file to disk.'; public $uploadExtensionErrorMessage = 'A PHP extension caused the upload to fail.'; public $uploadErrorMessage = 'The file could not be uploaded.'; } PK]'Validator/Constraints/Count.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Count extends Constraint { public $minMessage = 'This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.'; public $maxMessage = 'This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.'; public $exactMessage = 'This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.'; public $min; public $max; public function __construct($options = null) { if (null !== $options && !is_array($options)) { $options = array( 'min' => $options, 'max' => $options, ); } parent::__construct($options); if (null === $this->min && null === $this->max) { throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max')); } } } PK]aHβ  )Validator/Constraints/ChoiceValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * ChoiceValidator validates that the value is one of the expected values. * * @author Fabien Potencier * @author Florian Eckerstorfer * @author Bernhard Schussek * * @api */ class ChoiceValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (!$constraint->choices && !$constraint->callback) { throw new ConstraintDefinitionException('Either "choices" or "callback" must be specified on constraint Choice'); } if (null === $value) { return; } if ($constraint->multiple && !is_array($value)) { throw new UnexpectedTypeException($value, 'array'); } if ($constraint->callback) { if (is_callable(array($this->context->getClassName(), $constraint->callback))) { $choices = call_user_func(array($this->context->getClassName(), $constraint->callback)); } elseif (is_callable($constraint->callback)) { $choices = call_user_func($constraint->callback); } else { throw new ConstraintDefinitionException('The Choice constraint expects a valid callback'); } } else { $choices = $constraint->choices; } if ($constraint->multiple) { foreach ($value as $_value) { if (!in_array($_value, $choices, $constraint->strict)) { $this->context->addViolation($constraint->multipleMessage, array('{{ value }}' => $_value)); } } $count = count($value); if ($constraint->min !== null && $count < $constraint->min) { $this->context->addViolation($constraint->minMessage, array('{{ limit }}' => $constraint->min), null, (int) $constraint->min); return; } if ($constraint->max !== null && $count > $constraint->max) { $this->context->addViolation($constraint->maxMessage, array('{{ limit }}' => $constraint->max), null, (int) $constraint->max); return; } } elseif (!in_array($value, $choices, $constraint->strict)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK]ٜ?Validator/Constraints/True.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class True extends Constraint { public $message = 'This value should be true.'; } PK]+Validator/Constraints/Iban.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation */ class Iban extends Constraint { public $message = 'This is not a valid International Bank Account Number (IBAN).'; } PK]l˘ %Validator/Constraints/IpValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid IP address * * @author Bernhard Schussek * @author Joseph Bielawski * * @api */ class IpValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; switch ($constraint->version) { case Ip::V4: $flag = FILTER_FLAG_IPV4; break; case Ip::V6: $flag = FILTER_FLAG_IPV6; break; case Ip::V4_NO_PRIV: $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE; break; case Ip::V6_NO_PRIV: $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE; break; case Ip::ALL_NO_PRIV: $flag = FILTER_FLAG_NO_PRIV_RANGE; break; case Ip::V4_NO_RES: $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE; break; case Ip::V6_NO_RES: $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE; break; case Ip::ALL_NO_RES: $flag = FILTER_FLAG_NO_RES_RANGE; break; case Ip::V4_ONLY_PUBLIC: $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE; break; case Ip::V6_ONLY_PUBLIC: $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE; break; case Ip::ALL_ONLY_PUBLIC: $flag = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE; break; default: $flag = null; break; } if (!filter_var($value, FILTER_VALIDATE_IP, $flag)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK]Q+Validator/Constraints/LanguageValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid language code * * @author Bernhard Schussek * * @api */ class LanguageValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $languages = Intl::getLanguageBundle()->getLanguageNames(); if (!isset($languages[$value])) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK]b+'Validator/Constraints/LuhnValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates a PAN using the LUHN Algorithm * * For a list of example card numbers that are used to test this * class, please see the LuhnValidatorTest class. * * @see http://en.wikipedia.org/wiki/Luhn_algorithm * @author Tim Nagel * @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/ */ class LuhnValidator extends ConstraintValidator { /** * Validates a creditcard number with the Luhn algorithm. * * @param mixed $value * @param Constraint $constraint */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } /** * need to work with strings only because long numbers are treated as floats and don't work with strlen */ if (!is_string($value)) { throw new UnexpectedTypeException($value, 'string'); } if (!is_numeric($value)) { $this->context->addViolation($constraint->message); return; } $length = strlen($value); $oddLength = $length % 2; for ($sum = 0, $i = $length - 1; $i >= 0; $i--) { $digit = (int) $value[$i]; $sum += (($i % 2) === $oddLength) ? array_sum(str_split($digit * 2)) : $digit; } if ($sum === 0 || ($sum % 10) !== 0) { $this->context->addViolation($constraint->message); } } } PK] y(Validator/Constraints/BlankValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class BlankValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if ('' !== $value && null !== $value) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK]5(Validator/Constraints/EmailValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class EmailValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $valid = filter_var($value, FILTER_VALIDATE_EMAIL); if ($valid) { $host = substr($value, strpos($value, '@') + 1); // Check for host DNS resource records if ($valid && $constraint->checkMX) { $valid = $this->checkMX($host); } elseif ($valid && $constraint->checkHost) { $valid = $this->checkHost($host); } } if (!$valid) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } /** * Check DNS Records for MX type. * * @param string $host Host * * @return Boolean */ private function checkMX($host) { return checkdnsrr($host, 'MX'); } /** * Check if one of MX, A or AAAA DNS RR exists. * * @param string $host Host * * @return Boolean */ private function checkHost($host) { return $this->checkMX($host) || (checkdnsrr($host, "A") || checkdnsrr($host, "AAAA")); } } PK]ɑ55'Validator/Constraints/TrueValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class TrueValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (true !== $value && 1 !== $value && '1' !== $value) { $this->context->addViolation($constraint->message); } } } PK]^T (Validator/Constraints/FalseValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class FalseValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || false === $value || 0 === $value || '0' === $value) { return; } $this->context->addViolation($constraint->message); } } PK]_Validator/Constraints/Image.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @api */ class Image extends File { public $mimeTypes = 'image/*'; public $minWidth = null; public $maxWidth = null; public $maxHeight = null; public $minHeight = null; public $maxRatio = null; public $minRatio = null; public $allowSquare = true; public $allowLandscape = true; public $allowPortrait = true; public $mimeTypesMessage = 'This file is not a valid image.'; public $sizeNotDetectedMessage = 'The size of the image could not be detected.'; public $maxWidthMessage = 'The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.'; public $minWidthMessage = 'The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.'; public $maxHeightMessage = 'The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.'; public $minHeightMessage = 'The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.'; public $maxRatioMessage = 'The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.'; public $minRatioMessage = 'The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.'; public $allowSquareMessage = 'The image is square ({{ width }}x{{ height }}px). Square images are not allowed.'; public $allowLandscapeMessage = 'The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.'; public $allowPortraitMessage = 'The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.'; } PK]^r  "Validator/Constraints/Language.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Language extends Constraint { public $message = 'This value is not a valid language.'; } PK]F;)Validator/Constraints/LengthValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ class LengthValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $stringValue = (string) $value; if (function_exists('grapheme_strlen') && 'UTF-8' === $constraint->charset) { $length = grapheme_strlen($stringValue); } elseif (function_exists('mb_strlen')) { $length = mb_strlen($stringValue, $constraint->charset); } else { $length = strlen($stringValue); } if ($constraint->min == $constraint->max && $length != $constraint->min) { $this->context->addViolation($constraint->exactMessage, array( '{{ value }}' => $stringValue, '{{ limit }}' => $constraint->min, ), $value, (int) $constraint->min); return; } if (null !== $constraint->max && $length > $constraint->max) { $this->context->addViolation($constraint->maxMessage, array( '{{ value }}' => $stringValue, '{{ limit }}' => $constraint->max, ), $value, (int) $constraint->max); return; } if (null !== $constraint->min && $length < $constraint->min) { $this->context->addViolation($constraint->minMessage, array( '{{ value }}' => $stringValue, '{{ limit }}' => $constraint->min, ), $value, (int) $constraint->min); } } } PK]q;O!Validator/Constraints/Country.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Country extends Constraint { public $message = 'This value is not a valid country.'; } PK]Oqq2Validator/Constraints/LessThanOrEqualValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are less than or equal to the previous (<=). * * @author Daniel Holmes */ class LessThanOrEqualValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 <= $value2; } } PK]N3Validator/Constraints/Type.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Type extends Constraint { public $message = 'This value should be of type {{ type }}.'; public $type; /** * {@inheritDoc} */ public function getDefaultOption() { return 'type'; } /** * {@inheritDoc} */ public function getRequiredOptions() { return array('type'); } } PK]&+Validator/Constraints/NotBlankValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class NotBlankValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (false === $value || (empty($value) && '0' != $value)) { $this->context->addViolation($constraint->message); } } } PK];5t %Validator/ConstraintViolationList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Default implementation of {@ConstraintViolationListInterface}. * * @author Bernhard Schussek */ class ConstraintViolationList implements \IteratorAggregate, ConstraintViolationListInterface { /** * @var ConstraintViolationInterface[] */ private $violations = array(); /** * Creates a new constraint violation list. * * @param ConstraintViolationInterface[] $violations The constraint violations to add to the list */ public function __construct(array $violations = array()) { foreach ($violations as $violation) { $this->add($violation); } } /** * Converts the violation into a string for debugging purposes. * * @return string The violation as string. */ public function __toString() { $string = ''; foreach ($this->violations as $violation) { $string .= $violation."\n"; } return $string; } /** * {@inheritDoc} */ public function add(ConstraintViolationInterface $violation) { $this->violations[] = $violation; } /** * {@inheritDoc} */ public function addAll(ConstraintViolationListInterface $otherList) { foreach ($otherList as $violation) { $this->violations[] = $violation; } } /** * {@inheritDoc} */ public function get($offset) { if (!isset($this->violations[$offset])) { throw new \OutOfBoundsException(sprintf('The offset "%s" does not exist.', $offset)); } return $this->violations[$offset]; } /** * {@inheritDoc} */ public function has($offset) { return isset($this->violations[$offset]); } /** * {@inheritDoc} */ public function set($offset, ConstraintViolationInterface $violation) { $this->violations[$offset] = $violation; } /** * {@inheritDoc} */ public function remove($offset) { unset($this->violations[$offset]); } /** * {@inheritDoc} */ public function getIterator() { return new \ArrayIterator($this->violations); } /** * {@inheritDoc} */ public function count() { return count($this->violations); } /** * {@inheritDoc} */ public function offsetExists($offset) { return $this->has($offset); } /** * {@inheritDoc} */ public function offsetGet($offset) { return $this->get($offset); } /** * {@inheritDoc} */ public function offsetSet($offset, $violation) { if (null === $offset) { $this->add($violation); } else { $this->set($offset, $violation); } } /** * {@inheritDoc} */ public function offsetUnset($offset) { $this->remove($offset); } } PK]K}}Validator/DefaultTranslator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Validator\Exception\BadMethodCallException; use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Translation\TranslatorInterface; /** * Simple translator implementation that simply replaces the parameters in * the message IDs. * * Example usage: * * $translator = new DefaultTranslator(); * * echo $translator->trans( * 'This is a {{ var }}.', * array('{{ var }}' => 'donkey') * ); * * // -> This is a donkey. * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 3, * array('{{ count }}' => 'three') * ); * * // -> These are three donkeys. * * This translator does not support message catalogs, translation domains or * locales. Instead, it implements a subset of the capabilities of * {@link \Symfony\Component\Translation\Translator} and can be used in places * where translation is not required by default but should be optional. * * @author Bernhard Schussek */ class DefaultTranslator implements TranslatorInterface { /** * Interpolates the given message. * * Parameters are replaced in the message in the same manner that * {@link strtr()} uses. * * Example usage: * * $translator = new DefaultTranslator(); * * echo $translator->trans( * 'This is a {{ var }}.', * array('{{ var }}' => 'donkey') * ); * * // -> This is a donkey. * * @param string $id The message id * @param array $parameters An array of parameters for the message * @param string $domain Ignored * @param string $locale Ignored * * @return string The interpolated string */ public function trans($id, array $parameters = array(), $domain = null, $locale = null) { return strtr($id, $parameters); } /** * Interpolates the given choice message by choosing a variant according to a number. * * The variants are passed in the message ID using the format * "|". "" is chosen if the passed $number is * exactly 1. "" is chosen otherwise. * * This format is consistent with the format supported by * {@link \Symfony\Component\Translation\Translator}, but it does not * have the same expressiveness. While Translator supports intervals in * message translations, which are needed for languages other than English, * this translator does not. You should use Translator or a custom * implementation of {@link TranslatorInterface} if you need this or similar * functionality. * * Example usage: * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 0, * array('{{ count }}' => 0) * ); * * // -> These are 0 donkeys. * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 1, * array('{{ count }}' => 1) * ); * * // -> This is 1 donkey. * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 3, * array('{{ count }}' => 3) * ); * * // -> These are 3 donkeys. * * @param string $id The message id * @param integer $number The number to use to find the index of the message * @param array $parameters An array of parameters for the message * @param string $domain Ignored * @param string $locale Ignored * * @return string The translated string * * @throws InvalidArgumentException If the message id does not have the format * "singular|plural". */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null) { $ids = explode('|', $id); if (1 == $number) { return strtr($ids[0], $parameters); } if (!isset($ids[1])) { throw new InvalidArgumentException(sprintf('The message "%s" cannot be pluralized, because it is missing a plural (e.g. "There is one apple|There are %%count%% apples").', $id)); } return strtr($ids[1], $parameters); } /** * Not supported. * * @param string $locale The locale * * @throws BadMethodCallException */ public function setLocale($locale) { throw new BadMethodCallException('Unsupported method.'); } /** * Returns the locale of the translator. * * @return string Always returns 'en' */ public function getLocale() { return 'en'; } } PK]ƭWValidator/Constraint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Validator\Exception\InvalidOptionsException; use Symfony\Component\Validator\Exception\MissingOptionsException; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Contains the properties of a constraint definition. * * A constraint can be defined on a class, an option or a getter method. * The Constraint class encapsulates all the configuration required for * validating this class, option or getter result successfully. * * Constraint instances are immutable and serializable. * * @author Bernhard Schussek * * @api */ abstract class Constraint { /** * The name of the group given to all constraints with no explicit group * @var string */ const DEFAULT_GROUP = 'Default'; /** * Marks a constraint that can be put onto classes * @var string */ const CLASS_CONSTRAINT = 'class'; /** * Marks a constraint that can be put onto properties * @var string */ const PROPERTY_CONSTRAINT = 'property'; /** * @var array */ public $groups = array(self::DEFAULT_GROUP); /** * Initializes the constraint with options. * * You should pass an associative array. The keys should be the names of * existing properties in this class. The values should be the value for these * properties. * * Alternatively you can override the method getDefaultOption() to return the * name of an existing property. If no associative array is passed, this * property is set instead. * * You can force that certain options are set by overriding * getRequiredOptions() to return the names of these options. If any * option is not set here, an exception is thrown. * * @param mixed $options The options (as associative array) * or the value for the default * option (any other type) * * @throws InvalidOptionsException When you pass the names of non-existing * options * @throws MissingOptionsException When you don't pass any of the options * returned by getRequiredOptions() * @throws ConstraintDefinitionException When you don't pass an associative * array, but getDefaultOption() returns * null * * @api */ public function __construct($options = null) { $invalidOptions = array(); $missingOptions = array_flip((array) $this->getRequiredOptions()); if (is_array($options) && count($options) >= 1 && isset($options['value']) && !property_exists($this, 'value')) { $options[$this->getDefaultOption()] = $options['value']; unset($options['value']); } if (is_array($options) && count($options) > 0 && is_string(key($options))) { foreach ($options as $option => $value) { if (property_exists($this, $option)) { $this->$option = $value; unset($missingOptions[$option]); } else { $invalidOptions[] = $option; } } } elseif (null !== $options && ! (is_array($options) && count($options) === 0)) { $option = $this->getDefaultOption(); if (null === $option) { throw new ConstraintDefinitionException( sprintf('No default option is configured for constraint %s', get_class($this)) ); } if (property_exists($this, $option)) { $this->$option = $options; unset($missingOptions[$option]); } else { $invalidOptions[] = $option; } } if (count($invalidOptions) > 0) { throw new InvalidOptionsException( sprintf('The options "%s" do not exist in constraint %s', implode('", "', $invalidOptions), get_class($this)), $invalidOptions ); } if (count($missingOptions) > 0) { throw new MissingOptionsException( sprintf('The options "%s" must be set for constraint %s', implode('", "', array_keys($missingOptions)), get_class($this)), array_keys($missingOptions) ); } $this->groups = (array) $this->groups; } /** * Unsupported operation. */ public function __set($option, $value) { throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint %s', $option, get_class($this)), array($option)); } /** * Adds the given group if this constraint is in the Default group * * @param string $group * * @api */ public function addImplicitGroupName($group) { if (in_array(Constraint::DEFAULT_GROUP, $this->groups) && !in_array($group, $this->groups)) { $this->groups[] = $group; } } /** * Returns the name of the default option * * Override this method to define a default option. * * @return string * @see __construct() * * @api */ public function getDefaultOption() { return null; } /** * Returns the name of the required options * * Override this method if you want to define required options. * * @return array * @see __construct() * * @api */ public function getRequiredOptions() { return array(); } /** * Returns the name of the class that validates this constraint * * By default, this is the fully qualified name of the constraint class * suffixed with "Validator". You can override this method to change that * behaviour. * * @return string * * @api */ public function validatedBy() { return get_class($this).'Validator'; } /** * Returns whether the constraint can be put onto classes, properties or * both * * This method should return one or more of the constants * Constraint::CLASS_CONSTRAINT and Constraint::PROPERTY_CONSTRAINT. * * @return string|array One or more constant values * * @api */ public function getTargets() { return self::PROPERTY_CONSTRAINT; } } PK]n r Validator/ValidatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Validates values and graphs of objects and arrays. * * @author Bernhard Schussek * * @api */ interface ValidatorInterface { /** * Validates a value. * * The accepted values depend on the {@link MetadataFactoryInterface} * implementation. * * @param mixed $value The value to validate * @param array|null $groups The validation groups to validate. * @param Boolean $traverse Whether to traverse the value if it is traversable. * @param Boolean $deep Whether to traverse nested traversable values recursively. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api */ public function validate($value, $groups = null, $traverse = false, $deep = false); /** * Validates a property of a value against its current value. * * The accepted values depend on the {@link MetadataFactoryInterface} * implementation. * * @param mixed $containingValue The value containing the property. * @param string $property The name of the property to validate. * @param array|null $groups The validation groups to validate. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api */ public function validateProperty($containingValue, $property, $groups = null); /** * Validate a property of a value against a potential value. * * The accepted values depend on the {@link MetadataFactoryInterface} * implementation. * * @param string $containingValue The value containing the property. * @param string $property The name of the property to validate * @param string $value The value to validate against the * constraints of the property. * @param array|null $groups The validation groups to validate. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api */ public function validatePropertyValue($containingValue, $property, $value, $groups = null); /** * Validates a value against a constraint or a list of constraints. * * @param mixed $value The value to validate. * @param Constraint|Constraint[] $constraints The constraint(s) to validate against. * @param array|null $groups The validation groups to validate. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api */ public function validateValue($value, $constraints, $groups = null); /** * Returns the factory for metadata instances. * * @return MetadataFactoryInterface The metadata factory. * * @api */ public function getMetadataFactory(); } PK]U<<!Validator/ClassBasedInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * An object backed by a PHP class. * * @author Bernhard Schussek */ interface ClassBasedInterface { /** * Returns the name of the backing PHP class. * * @return string The name of the backing class. */ public function getClassName(); } PK]Y&Validator/MetadataFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Returns {@link MetadataInterface} instances for values. * * @author Bernhard Schussek */ interface MetadataFactoryInterface { /** * Returns the metadata for the given value. * * @param mixed $value Some value. * * @return MetadataInterface The metadata for the value. * * @throws Exception\NoSuchMetadataException If no metadata exists for the value. */ public function getMetadataFor($value); /** * Returns whether metadata exists for the given value. * * @param mixed $value Some value. * * @return Boolean Whether metadata exists for the value. */ public function hasMetadataFor($value); } PK],'*Validator/ConstraintValidatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * @author Bernhard Schussek * * @api */ interface ConstraintValidatorInterface { /** * Initializes the constraint validator. * * @param ExecutionContextInterface $context The current validation context */ public function initialize(ExecutionContextInterface $context); /** * Checks if the passed value is valid. * * @param mixed $value The value that should be validated * @param Constraint $constraint The constraint for the validation * * @api */ public function validate($value, Constraint $constraint); } PK]!Validator/ConstraintViolation.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Default implementation of {@ConstraintViolationInterface}. * * @author Bernhard Schussek */ class ConstraintViolation implements ConstraintViolationInterface { /** * @var string */ private $message; /** * @var string */ private $messageTemplate; /** * @var array */ private $messageParameters; /** * @var integer|null */ private $messagePluralization; /** * @var mixed */ private $root; /** * @var string */ private $propertyPath; /** * @var mixed */ private $invalidValue; /** * @var mixed */ private $code; /** * Creates a new constraint violation. * * @param string $message The violation message. * @param string $messageTemplate The raw violation message. * @param array $messageParameters The parameters to substitute * in the raw message. * @param mixed $root The value originally passed * to the validator. * @param string $propertyPath The property path from the * root value to the invalid * value. * @param mixed $invalidValue The invalid value causing the * violation. * @param integer|null $messagePluralization The pluralization parameter. * @param mixed $code The error code of the * violation, if any. */ public function __construct($message, $messageTemplate, array $messageParameters, $root, $propertyPath, $invalidValue, $messagePluralization = null, $code = null) { $this->message = $message; $this->messageTemplate = $messageTemplate; $this->messageParameters = $messageParameters; $this->messagePluralization = $messagePluralization; $this->root = $root; $this->propertyPath = $propertyPath; $this->invalidValue = $invalidValue; $this->code = $code; } /** * Converts the violation into a string for debugging purposes. * * @return string The violation as string. */ public function __toString() { if (is_object($this->root)) { $class = get_class($this->root); } elseif (is_array($this->root)) { $class = "Array"; } else { $class = (string) $this->root; } $propertyPath = (string) $this->propertyPath; $code = $this->code; if ('' !== $propertyPath && '[' !== $propertyPath[0] && '' !== $class) { $class .= '.'; } if (!empty($code)) { $code = ' (code '.$code.')'; } return $class.$propertyPath.":\n ".$this->getMessage().$code; } /** * {@inheritDoc} */ public function getMessageTemplate() { return $this->messageTemplate; } /** * {@inheritDoc} */ public function getMessageParameters() { return $this->messageParameters; } /** * {@inheritDoc} */ public function getMessagePluralization() { return $this->messagePluralization; } /** * {@inheritDoc} */ public function getMessage() { return $this->message; } /** * {@inheritDoc} */ public function getRoot() { return $this->root; } /** * {@inheritDoc} */ public function getPropertyPath() { return $this->propertyPath; } /** * {@inheritDoc} */ public function getInvalidValue() { return $this->invalidValue; } /** * {@inheritDoc} */ public function getCode() { return $this->code; } } PK]&{{'Validator/ValidatorBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Validator\Mapping\Cache\CacheInterface; use Symfony\Component\Translation\TranslatorInterface; use Doctrine\Common\Annotations\Reader; /** * A configurable builder for ValidatorInterface objects. * * @author Bernhard Schussek */ interface ValidatorBuilderInterface { /** * Adds an object initializer to the validator. * * @param ObjectInitializerInterface $initializer The initializer. * * @return ValidatorBuilderInterface The builder object. */ public function addObjectInitializer(ObjectInitializerInterface $initializer); /** * Adds a list of object initializers to the validator. * * @param array $initializers The initializer. * * @return ValidatorBuilderInterface The builder object. */ public function addObjectInitializers(array $initializers); /** * Adds an XML constraint mapping file to the validator. * * @param string $path The path to the mapping file. * * @return ValidatorBuilderInterface The builder object. */ public function addXmlMapping($path); /** * Adds a list of XML constraint mapping files to the validator. * * @param array $paths The paths to the mapping files. * * @return ValidatorBuilderInterface The builder object. */ public function addXmlMappings(array $paths); /** * Adds a YAML constraint mapping file to the validator. * * @param string $path The path to the mapping file. * * @return ValidatorBuilderInterface The builder object. */ public function addYamlMapping($path); /** * Adds a list of YAML constraint mappings file to the validator. * * @param array $paths The paths to the mapping files. * * @return ValidatorBuilderInterface The builder object. */ public function addYamlMappings(array $paths); /** * Enables constraint mapping using the given static method. * * @param string $methodName The name of the method. * * @return ValidatorBuilderInterface The builder object. */ public function addMethodMapping($methodName); /** * Enables constraint mapping using the given static methods. * * @param array $methodNames The names of the methods. * * @return ValidatorBuilderInterface The builder object. */ public function addMethodMappings(array $methodNames); /** * Enables annotation based constraint mapping. * * @param Reader $annotationReader The annotation reader to be used. * * @return ValidatorBuilderInterface The builder object. */ public function enableAnnotationMapping(Reader $annotationReader = null); /** * Disables annotation based constraint mapping. * * @return ValidatorBuilderInterface The builder object. */ public function disableAnnotationMapping(); /** * Sets the class metadata factory used by the validator. * * @param MetadataFactoryInterface $metadataFactory The metadata factory. * * @return ValidatorBuilderInterface The builder object. */ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory); /** * Sets the cache for caching class metadata. * * @param CacheInterface $cache The cache instance. * * @return ValidatorBuilderInterface The builder object. */ public function setMetadataCache(CacheInterface $cache); /** * Sets the constraint validator factory used by the validator. * * @param ConstraintValidatorFactoryInterface $validatorFactory The validator factory. * * @return ValidatorBuilderInterface The builder object. */ public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory); /** * Sets the translator used for translating violation messages. * * @param TranslatorInterface $translator The translator instance. * * @return ValidatorBuilderInterface The builder object. */ public function setTranslator(TranslatorInterface $translator); /** * Sets the default translation domain of violation messages. * * The same message can have different translations in different domains. * Pass the domain that is used for violation messages by default to this * method. * * @param string $translationDomain The translation domain of the violation messages. * * @return ValidatorBuilderInterface The builder object. */ public function setTranslationDomain($translationDomain); /** * Sets the property accessor for resolving property paths. * * @param PropertyAccessorInterface $propertyAccessor The property accessor. * * @return ValidatorBuilderInterface The builder object. */ public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor); /** * Builds and returns a new validator object. * * @return ValidatorInterface The built validator. */ public function getValidator(); } PK]bh0Validator/PropertyMetadataContainerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A container for {@link PropertyMetadataInterface} instances. * * @author Bernhard Schussek */ interface PropertyMetadataContainerInterface { /** * Check if there's any metadata attached to the given named property. * * @param string $property The property name. * * @return Boolean */ public function hasPropertyMetadata($property); /** * Returns all metadata instances for the given named property. * * If your implementation does not support properties, simply throw an * exception in this method (for example a BadMethodCallException). * * @param string $property The property name. * * @return PropertyMetadataInterface[] A list of metadata instances. Empty if * no metadata exists for the property. */ public function getPropertyMetadata($property); } PK]R'*Validator/ConstraintViolationInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A violation of a constraint that happened during validation. * * For each constraint that fails during validation one or more violations are * created. The violations store the violation message, the path to the failing * element in the validation graph and the root element that was originally * passed to the validator. For example, take the following graph: * *
 * (Person)---(firstName: string)
 *      \
 *   (address: Address)---(street: string)
 * 
* * If the Person object is validated and validation fails for the * "firstName" property, the generated violation has the Person * instance as root and the property path "firstName". If validation fails * for the "street" property of the related Address instance, the root * element is still the person, but the property path is "address.street". * * @author Bernhard Schussek * * @api */ interface ConstraintViolationInterface { /** * Returns the violation message. * * @return string The violation message. * * @api */ public function getMessage(); /** * Returns the raw violation message. * * The raw violation message contains placeholders for the parameters * returned by {@link getMessageParameters}. Typically you'll pass the * message template and parameters to a translation engine. * * @return string The raw violation message. * * @api */ public function getMessageTemplate(); /** * Returns the parameters to be inserted into the raw violation message. * * @return array A possibly empty list of parameters indexed by the names * that appear in the message template. * * @see getMessageTemplate * * @api */ public function getMessageParameters(); /** * Returns a number for pluralizing the violation message. * * For example, the message template could have different translation based * on a parameter "choices": * *
    *
  • Please select exactly one entry. (choices=1)
  • *
  • Please select two entries. (choices=2)
  • *
* * This method returns the value of the parameter for choosing the right * pluralization form (in this case "choices"). * * @return integer|null The number to use to pluralize of the message. */ public function getMessagePluralization(); /** * Returns the root element of the validation. * * @return mixed The value that was passed originally to the validator when * the validation was started. Because the validator traverses * the object graph, the value at which the violation occurs * is not necessarily the value that was originally validated. * * @api */ public function getRoot(); /** * Returns the property path from the root element to the violation. * * @return string The property path indicates how the validator reached * the invalid value from the root element. If the root * element is a Person instance with a property * "address" that contains an Address instance * with an invalid property "street", the generated property * path is "address.street". Property access is denoted by * dots, while array access is denoted by square brackets, * for example "addresses[1].street". * * @api */ public function getPropertyPath(); /** * Returns the value that caused the violation. * * @return mixed The invalid value that caused the validated constraint to * fail. * * @api */ public function getInvalidValue(); /** * Returns a machine-digestible error code for the violation. * * @return mixed The error code. */ public function getCode(); } PK]SUU,Validator/GroupSequenceProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Defines the interface for a group sequence provider. */ interface GroupSequenceProviderInterface { /** * Returns which validation groups should be used for a certain state * of the object. * * @return array An array of validation groups */ public function getGroupSequence(); } PK]SqK K Validator/MetadataInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A container for validation metadata. * * The container contains constraints that may belong to different validation * groups. Constraints for a specific group can be fetched by calling * {@link findConstraints}. * * Implement this interface to add validation metadata to your own metadata * layer. Each metadata may have named properties. Each property can be * represented by one or more {@link PropertyMetadataInterface} instances that * are returned by {@link getPropertyMetadata}. Since * PropertyMetadataInterface inherits from MetadataInterface, * each property may be divided into further properties. * * The {@link accept} method of each metadata implements the Visitor pattern. * The method should forward the call to the visitor's * {@link ValidationVisitorInterface::visit} method and additionally call * accept() on all structurally related metadata instances. * * For example, to store constraints for PHP classes and their properties, * create a class ClassMetadata (implementing MetadataInterface) * and a class PropertyMetadata (implementing PropertyMetadataInterface). * ClassMetadata::getPropertyMetadata($property) returns all * PropertyMetadata instances for a property of that class. Its * accept()-method simply forwards to ValidationVisitorInterface::visit() * and calls accept() on all contained PropertyMetadata * instances, which themselves call ValidationVisitorInterface::visit() * again. * * @author Bernhard Schussek */ interface MetadataInterface { /** * Implementation of the Visitor design pattern. * * Calls {@link ValidationVisitorInterface::visit} and then forwards the * accept()-call to all property metadata instances. * * @param ValidationVisitorInterface $visitor The visitor implementing the validation logic. * @param mixed $value The value to validate. * @param string|string[] $group The validation group to validate in. * @param string $propertyPath The current property path in the validation graph. */ public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath); /** * Returns all constraints for a given validation group. * * @param string $group The validation group. * * @return Constraint[] A list of constraint instances. */ public function findConstraints($group); } PK]}`'Validator/PropertyMetadataInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A container for validation metadata of a property. * * What exactly you define as "property" is up to you. The validator expects * implementations of {@link MetadataInterface} that contain constraints and * optionally a list of named properties that also have constraints (and may * have further sub properties). Such properties are mapped by implementations * of this interface. * * @author Bernhard Schussek * * @see MetadataInterface */ interface PropertyMetadataInterface extends MetadataInterface { /** * Returns the name of the property. * * @return string The property name. */ public function getPropertyName(); /** * Extracts the value of the property from the given container. * * @param mixed $containingValue The container to extract the property value from. * * @return mixed The value of the property. */ public function getPropertyValue($containingValue); } PK]KO1Validator/ConstraintValidatorFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Specifies an object able to return the correct ConstraintValidatorInterface * instance given a Constraint object. */ interface ConstraintValidatorFactoryInterface { /** * Given a Constraint, this returns the ConstraintValidatorInterface * object that should be used to verify its validity. * * @param Constraint $constraint The source constraint * * @return ConstraintValidatorInterface */ public function getInstance(Constraint $constraint); } PK]xfJJValidator/Validation.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Entry point for the Validator component. * * @author Bernhard Schussek */ final class Validation { /** * Creates a new validator. * * If you want to configure the validator, use * {@link createValidatorBuilder()} instead. * * @return ValidatorInterface The new validator. */ public static function createValidator() { return self::createValidatorBuilder()->getValidator(); } /** * Creates a configurable builder for validator objects. * * @return ValidatorBuilderInterface The new builder. */ public static function createValidatorBuilder() { return new ValidatorBuilder(); } /** * This class cannot be instantiated. */ private function __construct() { } } PK]AbI̲Validator/ValidationVisitor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Validator\Exception\NoSuchMetadataException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Translation\TranslatorInterface; /** * Default implementation of {@link ValidationVisitorInterface} and * {@link GlobalExecutionContextInterface}. * * @author Bernhard Schussek */ class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionContextInterface { /** * @var mixed */ private $root; /** * @var MetadataFactoryInterface */ private $metadataFactory; /** * @var ConstraintValidatorFactoryInterface */ private $validatorFactory; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var array */ private $objectInitializers; /** * @var ConstraintViolationList */ private $violations; /** * @var array */ private $validatedObjects = array(); /** * Creates a new validation visitor. * * @param mixed $root The value passed to the validator. * @param MetadataFactoryInterface $metadataFactory The factory for obtaining metadata instances. * @param ConstraintValidatorFactoryInterface $validatorFactory The factory for creating constraint validators. * @param TranslatorInterface $translator The translator for translating violation messages. * @param string|null $translationDomain The domain of the translation messages. * @param ObjectInitializerInterface[] $objectInitializers The initializers for preparing objects before validation. * * @throws UnexpectedTypeException If any of the object initializers is not an instance of ObjectInitializerInterface */ public function __construct($root, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = null, array $objectInitializers = array()) { foreach ($objectInitializers as $initializer) { if (!$initializer instanceof ObjectInitializerInterface) { throw new UnexpectedTypeException($initializer, 'Symfony\Component\Validator\ObjectInitializerInterface'); } } $this->root = $root; $this->metadataFactory = $metadataFactory; $this->validatorFactory = $validatorFactory; $this->translator = $translator; $this->translationDomain = $translationDomain; $this->objectInitializers = $objectInitializers; $this->violations = new ConstraintViolationList(); } /** * {@inheritdoc} */ public function visit(MetadataInterface $metadata, $value, $group, $propertyPath) { $context = new ExecutionContext( $this, $this->translator, $this->translationDomain, $metadata, $value, $group, $propertyPath ); $context->validateValue($value, $metadata->findConstraints($group)); } /** * {@inheritdoc} */ public function validate($value, $group, $propertyPath, $traverse = false, $deep = false) { if (null === $value) { return; } if (is_object($value)) { $hash = spl_object_hash($value); // Exit, if the object is already validated for the current group if (isset($this->validatedObjects[$hash][$group])) { return; } // Remember validating this object before starting and possibly // traversing the object graph $this->validatedObjects[$hash][$group] = true; foreach ($this->objectInitializers as $initializer) { if (!$initializer instanceof ObjectInitializerInterface) { throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.'); } $initializer->initialize($value); } } // Validate arrays recursively by default, otherwise every driver needs // to implement special handling for arrays. // https://github.com/symfony/symfony/issues/6246 if (is_array($value) || ($traverse && $value instanceof \Traversable)) { foreach ($value as $key => $element) { // Ignore any scalar values in the collection if (is_object($element) || is_array($element)) { // Only repeat the traversal if $deep is set $this->validate($element, $group, $propertyPath.'['.$key.']', $deep, $deep); } } try { $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath); } catch (NoSuchMetadataException $e) { // Metadata doesn't necessarily have to exist for // traversable objects, because we know how to validate // them anyway. Optionally, additional metadata is supported. } } else { $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath); } } /** * {@inheritdoc} */ public function getViolations() { return $this->violations; } /** * {@inheritdoc} */ public function getRoot() { return $this->root; } /** * {@inheritdoc} */ public function getVisitor() { return $this; } /** * {@inheritdoc} */ public function getValidatorFactory() { return $this->validatorFactory; } /** * {@inheritdoc} */ public function getMetadataFactory() { return $this->metadataFactory; } } PK]T*Validator/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base ExceptionInterface for the Validator component. * * @author Bernhard Schussek */ interface ExceptionInterface { } PK]z(Validator/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base RuntimeException for the Validator component. * * @author Bernhard Schussek */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK]x/Validator/Exception/NoSuchMetadataException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * @author Bernhard Schussek */ class NoSuchMetadataException extends ValidatorException { } PK]M#^^0Validator/Exception/GroupDefinitionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class GroupDefinitionException extends ValidatorException { } PK]LЉRR/Validator/Exception/InvalidOptionsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class InvalidOptionsException extends ValidatorException { private $options; public function __construct($message, array $options) { parent::__construct($message); $this->options = $options; } public function getOptions() { return $this->options; } } PK]y.Validator/Exception/BadMethodCallException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base BadMethodCallException for the Validator component. * * @author Bernhard Schussek */ class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface { } PK]k1+WW*Validator/Exception/ValidatorException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class ValidatorException extends \RuntimeException { } PK]b<</Validator/Exception/UnexpectedTypeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class UnexpectedTypeException extends ValidatorException { public function __construct($value, $expectedType) { parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value))); } } PK]\0Validator/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base InvalidArgumentException for the Validator component. * * @author Bernhard Schussek */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PK]uRR/Validator/Exception/MissingOptionsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class MissingOptionsException extends ValidatorException { private $options; public function __construct($message, array $options) { parent::__construct($message); $this->options = $options; } public function getOptions() { return $this->options; } } PK]QVV(Validator/Exception/MappingException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class MappingException extends ValidatorException { } PK]1"cc5Validator/Exception/ConstraintDefinitionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class ConstraintDefinitionException extends ValidatorException { } PK]޽/!/!Validator/ExecutionContext.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Translation\TranslatorInterface; /** * Default implementation of {@link ExecutionContextInterface}. * * This class is immutable by design. * * @author Fabien Potencier * @author Bernhard Schussek */ class ExecutionContext implements ExecutionContextInterface { /** * @var GlobalExecutionContextInterface */ private $globalContext; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var MetadataInterface */ private $metadata; /** * @var mixed */ private $value; /** * @var string */ private $group; /** * @var string */ private $propertyPath; /** * Creates a new execution context. * * @param GlobalExecutionContextInterface $globalContext The global context storing node-independent state. * @param TranslatorInterface $translator The translator for translating violation messages. * @param null|string $translationDomain The domain of the validation messages. * @param MetadataInterface $metadata The metadata of the validated node. * @param mixed $value The value of the validated node. * @param string $group The current validation group. * @param string $propertyPath The property path to the current node. */ public function __construct(GlobalExecutionContextInterface $globalContext, TranslatorInterface $translator, $translationDomain = null, MetadataInterface $metadata = null, $value = null, $group = null, $propertyPath = '') { if (null === $group) { $group = Constraint::DEFAULT_GROUP; } $this->globalContext = $globalContext; $this->translator = $translator; $this->translationDomain = $translationDomain; $this->metadata = $metadata; $this->value = $value; $this->propertyPath = $propertyPath; $this->group = $group; } /** * {@inheritdoc} */ public function addViolation($message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null) { if (null === $pluralization) { $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain); } else { try { $translatedMessage = $this->translator->transChoice($message, $pluralization, $params, $this->translationDomain); } catch (\InvalidArgumentException $e) { $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain); } } $this->globalContext->getViolations()->add(new ConstraintViolation( $translatedMessage, $message, $params, $this->globalContext->getRoot(), $this->propertyPath, // check using func_num_args() to allow passing null values func_num_args() >= 3 ? $invalidValue : $this->value, $pluralization, $code )); } /** * {@inheritdoc} */ public function addViolationAt($subPath, $message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null) { $this->globalContext->getViolations()->add(new ConstraintViolation( null === $pluralization ? $this->translator->trans($message, $params, $this->translationDomain) : $this->translator->transChoice($message, $pluralization, $params, $this->translationDomain), $message, $params, $this->globalContext->getRoot(), $this->getPropertyPath($subPath), // check using func_num_args() to allow passing null values func_num_args() >= 4 ? $invalidValue : $this->value, $pluralization, $code )); } /** * {@inheritdoc} */ public function getViolations() { return $this->globalContext->getViolations(); } /** * {@inheritdoc} */ public function getRoot() { return $this->globalContext->getRoot(); } /** * {@inheritdoc} */ public function getPropertyPath($subPath = '') { if ('' != $subPath && '' !== $this->propertyPath && '[' !== $subPath[0]) { return $this->propertyPath.'.'.$subPath; } return $this->propertyPath.$subPath; } /** * {@inheritdoc} */ public function getClassName() { if ($this->metadata instanceof ClassBasedInterface) { return $this->metadata->getClassName(); } return null; } /** * {@inheritdoc} */ public function getPropertyName() { if ($this->metadata instanceof PropertyMetadataInterface) { return $this->metadata->getPropertyName(); } return null; } /** * {@inheritdoc} */ public function getValue() { return $this->value; } /** * {@inheritdoc} */ public function getGroup() { return $this->group; } /** * {@inheritdoc} */ public function getMetadata() { return $this->metadata; } /** * {@inheritdoc} */ public function getMetadataFor($value) { return $this->globalContext->getMetadataFactory()->getMetadataFor($value); } /** * {@inheritdoc} */ public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false) { $propertyPath = $this->getPropertyPath($subPath); foreach ($this->resolveGroups($groups) as $group) { $this->globalContext->getVisitor()->validate($value, $group, $propertyPath, $traverse, $deep); } } /** * {@inheritdoc} */ public function validateValue($value, $constraints, $subPath = '', $groups = null) { $constraints = is_array($constraints) ? $constraints : array($constraints); if (null === $groups && '' === $subPath) { $context = clone $this; $context->value = $value; $context->executeConstraintValidators($value, $constraints); return; } $propertyPath = $this->getPropertyPath($subPath); foreach ($this->resolveGroups($groups) as $group) { $context = clone $this; $context->value = $value; $context->group = $group; $context->propertyPath = $propertyPath; $context->executeConstraintValidators($value, $constraints); } } /** * {@inheritdoc} */ public function getMetadataFactory() { return $this->globalContext->getMetadataFactory(); } /** * Executes the validators of the given constraints for the given value. * * @param mixed $value The value to validate. * @param Constraint[] $constraints The constraints to match against. */ private function executeConstraintValidators($value, array $constraints) { foreach ($constraints as $constraint) { $validator = $this->globalContext->getValidatorFactory()->getInstance($constraint); $validator->initialize($this); $validator->validate($value, $constraint); } } /** * Returns an array of group names. * * @param null|string|string[] $groups The groups to resolve. If a single string is * passed, it is converted to an array. If null * is passed, an array containing the current * group of the context is returned. * * @return array An array of validation groups. */ private function resolveGroups($groups) { return $groups ? (array) $groups : (array) $this->group; } } PK]z911(Validator/ObjectInitializerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Prepares an object for validation. * * Concrete implementations of this interface are used by {@link ValidationVisitorInterface} * to initialize objects just before validating them. * * @author Fabien Potencier * @author Bernhard Schussek * * @api */ interface ObjectInitializerInterface { /** * Initializes an object just before validation. * * @param object $object The object to validate * * @api */ public function initialize($object); } PK]+s(Validator/ConstraintValidatorFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Validator\Constraints\ExpressionValidator; /** * Default implementation of the ConstraintValidatorFactoryInterface. * * This enforces the convention that the validatedBy() method on any * Constraint will return the class name of the ConstraintValidator that * should validate the Constraint. * * @author Bernhard Schussek */ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface { protected $validators = array(); /** * @var PropertyAccessorInterface */ private $propertyAccessor; public function __construct(PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } /** * {@inheritDoc} */ public function getInstance(Constraint $constraint) { $className = $constraint->validatedBy(); // The second condition is a hack that is needed when CollectionValidator // calls itself recursively (Collection constraints can be nested). // Since the context of the validator is overwritten when initialize() // is called for the nested constraint, the outer validator is // acting on the wrong context when the nested validation terminates. // // A better solution - which should be approached in Symfony 3.0 - is to // remove the initialize() method and pass the context as last argument // to validate() instead. if (!isset($this->validators[$className]) || 'Symfony\Component\Validator\Constraints\CollectionValidator' === $className) { $this->validators[$className] = 'validator.expression' === $className ? new ExpressionValidator($this->propertyAccessor) : new $className(); } return $this->validators[$className]; } } PK]8Wc-Validator/GlobalExecutionContextInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Stores the node-independent state of a validation run. * * When the validator validates a graph of objects, it uses two classes to * store the state during the validation: * *
    *
  • For each node in the validation graph (objects, properties, getters) the * validator creates an instance of {@link ExecutionContextInterface} that * stores the information about that node.
  • *
  • One single GlobalExecutionContextInterface stores the state * that is independent of the current node.
  • *
* * @author Bernhard Schussek */ interface GlobalExecutionContextInterface { /** * Returns the violations generated by the validator so far. * * @return ConstraintViolationListInterface A list of constraint violations. */ public function getViolations(); /** * Returns the value at which validation was started in the object graph. * * @return mixed The root value. * * @see ExecutionContextInterface::getRoot */ public function getRoot(); /** * Returns the visitor instance used to validate the object graph nodes. * * @return ValidationVisitorInterface The validation visitor. */ public function getVisitor(); /** * Returns the factory for constraint validators. * * @return ConstraintValidatorFactoryInterface The constraint validator factory. */ public function getValidatorFactory(); /** * Returns the factory for validation metadata objects. * * @return MetadataFactoryInterface The metadata factory. */ public function getMetadataFactory(); } PK]/;aa$Validator/Mapping/MemberMetadata.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\ValidationVisitorInterface; use Symfony\Component\Validator\ClassBasedInterface; use Symfony\Component\Validator\PropertyMetadataInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; abstract class MemberMetadata extends ElementMetadata implements PropertyMetadataInterface, ClassBasedInterface { public $class; public $name; public $property; public $cascaded = false; public $collectionCascaded = false; public $collectionCascadedDeeply = false; private $reflMember = array(); /** * Constructor. * * @param string $class The name of the class this member is defined on * @param string $name The name of the member * @param string $property The property the member belongs to */ public function __construct($class, $name, $property) { $this->class = $class; $this->name = $name; $this->property = $property; } public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null) { $visitor->visit($this, $value, $group, $propertyPath); if ($this->isCascaded()) { $visitor->validate($value, $propagatedGroup ?: $group, $propertyPath, $this->isCollectionCascaded(), $this->isCollectionCascadedDeeply()); } } /** * {@inheritDoc} */ public function addConstraint(Constraint $constraint) { if (!in_array(Constraint::PROPERTY_CONSTRAINT, (array) $constraint->getTargets())) { throw new ConstraintDefinitionException(sprintf( 'The constraint %s cannot be put on properties or getters', get_class($constraint) )); } if ($constraint instanceof Valid) { $this->cascaded = true; /* @var Valid $constraint */ $this->collectionCascaded = $constraint->traverse; $this->collectionCascadedDeeply = $constraint->deep; } else { parent::addConstraint($constraint); } return $this; } /** * Returns the names of the properties that should be serialized * * @return array */ public function __sleep() { return array_merge(parent::__sleep(), array( 'class', 'name', 'property', 'cascaded', 'collectionCascaded', 'collectionCascadedDeeply', )); } /** * Returns the name of the member * * @return string */ public function getName() { return $this->name; } /** * Returns the class this member is defined on * * @return string */ public function getClassName() { return $this->class; } /** * Returns the name of the property this member belongs to * * @return string The property name */ public function getPropertyName() { return $this->property; } /** * Returns whether this member is public * * @param object|string $objectOrClassName The object or the class name * * @return Boolean */ public function isPublic($objectOrClassName) { return $this->getReflectionMember($objectOrClassName)->isPublic(); } /** * Returns whether this member is protected * * @param object|string $objectOrClassName The object or the class name * * @return Boolean */ public function isProtected($objectOrClassName) { return $this->getReflectionMember($objectOrClassName)->isProtected(); } /** * Returns whether this member is private * * @param object|string $objectOrClassName The object or the class name * * @return Boolean */ public function isPrivate($objectOrClassName) { return $this->getReflectionMember($objectOrClassName)->isPrivate(); } /** * Returns whether objects stored in this member should be validated * * @return Boolean */ public function isCascaded() { return $this->cascaded; } /** * Returns whether arrays or traversable objects stored in this member * should be traversed and validated in each entry * * @return Boolean */ public function isCollectionCascaded() { return $this->collectionCascaded; } /** * Returns whether arrays or traversable objects stored in this member * should be traversed recursively for inner arrays/traversable objects * * @return Boolean */ public function isCollectionCascadedDeeply() { return $this->collectionCascadedDeeply; } /** * Returns the Reflection instance of the member * * @param object|string $objectOrClassName The object or the class name * * @return object */ public function getReflectionMember($objectOrClassName) { $className = is_string($objectOrClassName) ? $objectOrClassName : get_class($objectOrClassName); if (!isset($this->reflMember[$className])) { $this->reflMember[$className] = $this->newReflectionMember($objectOrClassName); } return $this->reflMember[$className]; } /** * Creates a new Reflection instance for the member * * @param object|string $objectOrClassName The object or the class name * * @return mixed Reflection class */ abstract protected function newReflectionMember($objectOrClassName); } PK]d#[N *Validator/Mapping/ClassMetadataFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\Exception\NoSuchMetadataException; use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; use Symfony\Component\Validator\Mapping\Cache\CacheInterface; /** * A factory for creating metadata for PHP classes. * * @author Bernhard Schussek */ class ClassMetadataFactory implements MetadataFactoryInterface { /** * The loader for loading the class metadata * @var LoaderInterface */ protected $loader; /** * The cache for caching class metadata * @var CacheInterface */ protected $cache; protected $loadedClasses = array(); public function __construct(LoaderInterface $loader = null, CacheInterface $cache = null) { $this->loader = $loader; $this->cache = $cache; } /** * {@inheritdoc} */ public function getMetadataFor($value) { if (!is_object($value) && !is_string($value)) { throw new NoSuchMetadataException(sprintf('Cannot create metadata for non-objects. Got: %s', gettype($value))); } $class = ltrim(is_object($value) ? get_class($value) : $value, '\\'); if (isset($this->loadedClasses[$class])) { return $this->loadedClasses[$class]; } if (null !== $this->cache && false !== ($this->loadedClasses[$class] = $this->cache->read($class))) { return $this->loadedClasses[$class]; } if (!class_exists($class) && !interface_exists($class)) { throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class)); } $metadata = new ClassMetadata($class); // Include constraints from the parent class if ($parent = $metadata->getReflectionClass()->getParentClass()) { $metadata->mergeConstraints($this->getMetadataFor($parent->name)); } // Include constraints from all implemented interfaces foreach ($metadata->getReflectionClass()->getInterfaces() as $interface) { if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) { continue; } $metadata->mergeConstraints($this->getMetadataFor($interface->name)); } if (null !== $this->loader) { $this->loader->loadClassMetadata($metadata); } if (null !== $this->cache) { $this->cache->write($metadata); } return $this->loadedClasses[$class] = $metadata; } /** * {@inheritdoc} */ public function hasMetadataFor($value) { if (!is_object($value) && !is_string($value)) { return false; } $class = ltrim(is_object($value) ? get_class($value) : $value, '\\'); if (class_exists($class) || interface_exists($class)) { return true; } return false; } } PK]۔.Validator/Mapping/BlackholeMetadataFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\MetadataFactoryInterface; /** * Simple implementation of MetadataFactoryInterface that can be used when using ValidatorInterface::validateValue(). * * @author Fabien Potencier */ class BlackholeMetadataFactory implements MetadataFactoryInterface { /** * @inheritdoc */ public function getMetadataFor($value) { throw new \LogicException('BlackholeClassMetadataFactory only works with ValidatorInterface::validateValue().'); } /** * @inheritdoc */ public function hasMetadataFor($value) { return false; } } PK]!" " %Validator/Mapping/ElementMetadata.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Constraint; abstract class ElementMetadata { /** * @var Constraint[] */ public $constraints = array(); /** * @var array */ public $constraintsByGroup = array(); /** * Returns the names of the properties that should be serialized. * * @return array */ public function __sleep() { return array( 'constraints', 'constraintsByGroup', ); } /** * Clones this object. */ public function __clone() { $constraints = $this->constraints; $this->constraints = array(); $this->constraintsByGroup = array(); foreach ($constraints as $constraint) { $this->addConstraint(clone $constraint); } } /** * Adds a constraint to this element. * * @param Constraint $constraint * * @return ElementMetadata */ public function addConstraint(Constraint $constraint) { $this->constraints[] = $constraint; foreach ($constraint->groups as $group) { $this->constraintsByGroup[$group][] = $constraint; } return $this; } /** * Returns all constraints of this element. * * @return Constraint[] An array of Constraint instances */ public function getConstraints() { return $this->constraints; } /** * Returns whether this element has any constraints. * * @return Boolean */ public function hasConstraints() { return count($this->constraints) > 0; } /** * Returns the constraints of the given group and global ones (* group). * * @param string $group The group name * * @return array An array with all Constraint instances belonging to the group */ public function findConstraints($group) { return isset($this->constraintsByGroup[$group]) ? $this->constraintsByGroup[$group] : array(); } } PK] r &Validator/Mapping/PropertyMetadata.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Exception\ValidatorException; class PropertyMetadata extends MemberMetadata { /** * Constructor. * * @param string $class The class this property is defined on * @param string $name The name of this property * * @throws ValidatorException */ public function __construct($class, $name) { if (!property_exists($class, $name)) { throw new ValidatorException(sprintf('Property %s does not exist in class %s', $name, $class)); } parent::__construct($class, $name, $name); } /** * {@inheritDoc} */ public function getPropertyValue($object) { return $this->getReflectionMember($object)->getValue($object); } /** * {@inheritDoc} */ protected function newReflectionMember($objectOrClassName) { $class = new \ReflectionClass($objectOrClassName); while (!$class->hasProperty($this->getName())) { $class = $class->getParentClass(); } $member = new \ReflectionProperty($class->getName(), $this->getName()); $member->setAccessible(true); return $member; } } PK]*(Validator/Mapping/Loader/FilesLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; /** * Creates mapping loaders for array of files. * * Abstract class, used by * * @author Bulat Shakirzyanov * * @see Symfony\Component\Validator\Mapping\Loader\YamlFileLoader * @see Symfony\Component\Validator\Mapping\Loader\XmlFileLoader */ abstract class FilesLoader extends LoaderChain { /** * Array of mapping files. * * @param array $paths Array of file paths */ public function __construct(array $paths) { parent::__construct($this->getFileLoaders($paths)); } /** * Array of mapping files. * * @param array $paths Array of file paths * * @return LoaderInterface[] Array of metadata loaders */ protected function getFileLoaders($paths) { $loaders = array(); foreach ($paths as $path) { $loaders[] = $this->getFileLoaderInstance($path); } return $loaders; } /** * Takes mapping file path. * * @param string $file * * @return LoaderInterface */ abstract protected function getFileLoaderInstance($file); } PK]'pkk+Validator/Mapping/Loader/YamlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Yaml\Parser as YamlParser; class YamlFileLoader extends FileLoader { private $yamlParser; /** * An array of YAML class descriptions * * @var array */ protected $classes = null; /** * {@inheritDoc} */ public function loadClassMetadata(ClassMetadata $metadata) { if (null === $this->classes) { if (!stream_is_local($this->file)) { throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $this->file)); } if (!file_exists($this->file)) { throw new \InvalidArgumentException(sprintf('File "%s" not found.', $this->file)); } if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } $this->classes = $this->yamlParser->parse(file_get_contents($this->file)); // empty file if (null === $this->classes) { return false; } // not an array if (!is_array($this->classes)) { throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $this->file)); } if (isset($this->classes['namespaces'])) { foreach ($this->classes['namespaces'] as $alias => $namespace) { $this->addNamespaceAlias($alias, $namespace); } unset($this->classes['namespaces']); } } // TODO validation if (isset($this->classes[$metadata->getClassName()])) { $yaml = $this->classes[$metadata->getClassName()]; if (isset($yaml['group_sequence_provider'])) { $metadata->setGroupSequenceProvider((bool) $yaml['group_sequence_provider']); } if (isset($yaml['group_sequence'])) { $metadata->setGroupSequence($yaml['group_sequence']); } if (isset($yaml['constraints']) && is_array($yaml['constraints'])) { foreach ($this->parseNodes($yaml['constraints']) as $constraint) { $metadata->addConstraint($constraint); } } if (isset($yaml['properties']) && is_array($yaml['properties'])) { foreach ($yaml['properties'] as $property => $constraints) { if (null !== $constraints) { foreach ($this->parseNodes($constraints) as $constraint) { $metadata->addPropertyConstraint($property, $constraint); } } } } if (isset($yaml['getters']) && is_array($yaml['getters'])) { foreach ($yaml['getters'] as $getter => $constraints) { if (null !== $constraints) { foreach ($this->parseNodes($constraints) as $constraint) { $metadata->addGetterConstraint($getter, $constraint); } } } } return true; } return false; } /** * Parses a collection of YAML nodes * * @param array $nodes The YAML nodes * * @return array An array of values or Constraint instances */ protected function parseNodes(array $nodes) { $values = array(); foreach ($nodes as $name => $childNodes) { if (is_numeric($name) && is_array($childNodes) && count($childNodes) == 1) { $options = current($childNodes); if (is_array($options)) { $options = $this->parseNodes($options); } $values[] = $this->newConstraint(key($childNodes), $options); } else { if (is_array($childNodes)) { $childNodes = $this->parseNodes($childNodes); } $values[$name] = $childNodes; } } return $values; } } PK]TO--QValidator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsdnu[ PK]Rᠯ+Validator/Mapping/Loader/XmlFilesLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; /** * Loads multiple xml mapping files * * @author Bulat Shakirzyanov * * @see Symfony\Component\Validator\Mapping\Loader\FilesLoader */ class XmlFilesLoader extends FilesLoader { /** * {@inheritDoc} */ public function getFileLoaderInstance($file) { return new XmlFileLoader($file); } } PK]ʚ'Validator/Mapping/Loader/FileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; abstract class FileLoader extends AbstractLoader { protected $file; /** * Constructor. * * @param string $file The mapping file to load * * @throws MappingException if the mapping file does not exist * @throws MappingException if the mapping file is not readable */ public function __construct($file) { if (!is_file($file)) { throw new MappingException(sprintf('The mapping file %s does not exist', $file)); } if (!is_readable($file)) { throw new MappingException(sprintf('The mapping file %s is not readable', $file)); } $this->file = $file; } } PK]kG++Validator/Mapping/Loader/AbstractLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Constraint; abstract class AbstractLoader implements LoaderInterface { /** * Contains all known namespaces indexed by their prefix * @var array */ protected $namespaces = array(); /** * Adds a namespace alias. * * @param string $alias The alias * @param string $namespace The PHP namespace */ protected function addNamespaceAlias($alias, $namespace) { $this->namespaces[$alias] = $namespace; } /** * Creates a new constraint instance for the given constraint name. * * @param string $name The constraint name. Either a constraint relative * to the default constraint namespace, or a fully * qualified class name * @param mixed $options The constraint options * * @return Constraint * * @throws MappingException If the namespace prefix is undefined */ protected function newConstraint($name, $options) { if (strpos($name, '\\') !== false && class_exists($name)) { $className = (string) $name; } elseif (strpos($name, ':') !== false) { list($prefix, $className) = explode(':', $name, 2); if (!isset($this->namespaces[$prefix])) { throw new MappingException(sprintf('Undefined namespace prefix "%s"', $prefix)); } $className = $this->namespaces[$prefix].$className; } else { $className = 'Symfony\\Component\\Validator\\Constraints\\'.$name; } return new $className($options); } } PK]>??,Validator/Mapping/Loader/LoaderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Mapping\ClassMetadata; interface LoaderInterface { /** * Load a Class Metadata. * * @param ClassMetadata $metadata A metadata * * @return Boolean */ public function loadClassMetadata(ClassMetadata $metadata); } PK];QF11*Validator/Mapping/Loader/XmlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Config\Util\XmlUtils; class XmlFileLoader extends FileLoader { /** * An array of SimpleXMLElement instances. * * @var \SimpleXMLElement[] */ protected $classes = null; /** * {@inheritDoc} */ public function loadClassMetadata(ClassMetadata $metadata) { if (null === $this->classes) { $this->classes = array(); $xml = $this->parseFile($this->file); foreach ($xml->namespace as $namespace) { $this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace)); } foreach ($xml->class as $class) { $this->classes[(string) $class['name']] = $class; } } if (isset($this->classes[$metadata->getClassName()])) { $xml = $this->classes[$metadata->getClassName()]; foreach ($xml->{'group-sequence-provider'} as $provider) { $metadata->setGroupSequenceProvider(true); } foreach ($xml->{'group-sequence'} as $groupSequence) { if (count($groupSequence->value) > 0) { $metadata->setGroupSequence($this->parseValues($groupSequence[0]->value)); } } foreach ($this->parseConstraints($xml->constraint) as $constraint) { $metadata->addConstraint($constraint); } foreach ($xml->property as $property) { foreach ($this->parseConstraints($property->constraint) as $constraint) { $metadata->addPropertyConstraint((string) $property['name'], $constraint); } } foreach ($xml->getter as $getter) { foreach ($this->parseConstraints($getter->constraint) as $constraint) { $metadata->addGetterConstraint((string) $getter['property'], $constraint); } } return true; } return false; } /** * Parses a collection of "constraint" XML nodes. * * @param \SimpleXMLElement $nodes The XML nodes * * @return array The Constraint instances */ protected function parseConstraints(\SimpleXMLElement $nodes) { $constraints = array(); foreach ($nodes as $node) { if (count($node) > 0) { if (count($node->value) > 0) { $options = $this->parseValues($node->value); } elseif (count($node->constraint) > 0) { $options = $this->parseConstraints($node->constraint); } elseif (count($node->option) > 0) { $options = $this->parseOptions($node->option); } else { $options = array(); } } elseif (strlen((string) $node) > 0) { $options = trim($node); } else { $options = null; } $constraints[] = $this->newConstraint((string) $node['name'], $options); } return $constraints; } /** * Parses a collection of "value" XML nodes. * * @param \SimpleXMLElement $nodes The XML nodes * * @return array The values */ protected function parseValues(\SimpleXMLElement $nodes) { $values = array(); foreach ($nodes as $node) { if (count($node) > 0) { if (count($node->value) > 0) { $value = $this->parseValues($node->value); } elseif (count($node->constraint) > 0) { $value = $this->parseConstraints($node->constraint); } else { $value = array(); } } else { $value = trim($node); } if (isset($node['key'])) { $values[(string) $node['key']] = $value; } else { $values[] = $value; } } return $values; } /** * Parses a collection of "option" XML nodes. * * @param \SimpleXMLElement $nodes The XML nodes * * @return array The options */ protected function parseOptions(\SimpleXMLElement $nodes) { $options = array(); foreach ($nodes as $node) { if (count($node) > 0) { if (count($node->value) > 0) { $value = $this->parseValues($node->value); } elseif (count($node->constraint) > 0) { $value = $this->parseConstraints($node->constraint); } else { $value = array(); } } else { $value = XmlUtils::phpize($node); if (is_string($value)) { $value = trim($value); } } $options[(string) $node['name']] = $value; } return $options; } /** * Parse a XML File. * * @param string $file Path of file * * @return \SimpleXMLElement * * @throws MappingException */ protected function parseFile($file) { try { $dom = XmlUtils::loadFile($file, __DIR__.'/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd'); } catch (\Exception $e) { throw new MappingException($e->getMessage(), $e->getCode(), $e); } return simplexml_import_dom($dom); } } PK](Validator/Mapping/Loader/LoaderChain.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * Calls multiple LoaderInterface instances in a chain * * This class accepts multiple instances of LoaderInterface to be passed to the * constructor. When loadClassMetadata() is called, the same method is called * in all of these loaders, regardless of whether any of them was * successful or not. * * @author Bernhard Schussek */ class LoaderChain implements LoaderInterface { protected $loaders; /** * Accepts a list of LoaderInterface instances * * @param LoaderInterface[] $loaders An array of LoaderInterface instances * * @throws MappingException If any of the loaders does not implement LoaderInterface */ public function __construct(array $loaders) { foreach ($loaders as $loader) { if (!$loader instanceof LoaderInterface) { throw new MappingException(sprintf('Class %s is expected to implement LoaderInterface', get_class($loader))); } } $this->loaders = $loaders; } /** * {@inheritDoc} */ public function loadClassMetadata(ClassMetadata $metadata) { $success = false; foreach ($this->loaders as $loader) { $success = $loader->loadClassMetadata($metadata) || $success; } return $success; } } PK]Tb/Validator/Mapping/Loader/StaticMethodLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; class StaticMethodLoader implements LoaderInterface { protected $methodName; public function __construct($methodName = 'loadValidatorMetadata') { $this->methodName = $methodName; } /** * {@inheritDoc} */ public function loadClassMetadata(ClassMetadata $metadata) { /** @var \ReflectionClass $reflClass */ $reflClass = $metadata->getReflectionClass(); if (!$reflClass->isInterface() && $reflClass->hasMethod($this->methodName)) { $reflMethod = $reflClass->getMethod($this->methodName); if ($reflMethod->isAbstract()) { return false; } if (!$reflMethod->isStatic()) { throw new MappingException(sprintf('The method %s::%s should be static', $reflClass->name, $this->methodName)); } if ($reflMethod->getDeclaringClass()->name != $reflClass->name) { return false; } $reflMethod->invoke(null, $metadata); return true; } return false; } } PK]?,Validator/Mapping/Loader/YamlFilesLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; /** * Loads multiple yaml mapping files * * @author Bulat Shakirzyanov * * @see Symfony\Component\Validator\Mapping\Loader\FilesLoader */ class YamlFilesLoader extends FilesLoader { /** * {@inheritDoc} */ public function getFileLoaderInstance($file) { return new YamlFileLoader($file); } } PK] lw#Q Q -Validator/Mapping/Loader/AnnotationLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Doctrine\Common\Annotations\Reader; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\GroupSequenceProvider; use Symfony\Component\Validator\Constraint; class AnnotationLoader implements LoaderInterface { protected $reader; public function __construct(Reader $reader) { $this->reader = $reader; } /** * {@inheritDoc} */ public function loadClassMetadata(ClassMetadata $metadata) { $reflClass = $metadata->getReflectionClass(); $className = $reflClass->name; $loaded = false; foreach ($this->reader->getClassAnnotations($reflClass) as $constraint) { if ($constraint instanceof GroupSequence) { $metadata->setGroupSequence($constraint->groups); } elseif ($constraint instanceof GroupSequenceProvider) { $metadata->setGroupSequenceProvider(true); } elseif ($constraint instanceof Constraint) { $metadata->addConstraint($constraint); } $loaded = true; } foreach ($reflClass->getProperties() as $property) { if ($property->getDeclaringClass()->name == $className) { foreach ($this->reader->getPropertyAnnotations($property) as $constraint) { if ($constraint instanceof Constraint) { $metadata->addPropertyConstraint($property->name, $constraint); } $loaded = true; } } } foreach ($reflClass->getMethods() as $method) { if ($method->getDeclaringClass()->name == $className) { foreach ($this->reader->getMethodAnnotations($method) as $constraint) { if ($constraint instanceof Callback) { $constraint->callback = $method->getName(); $constraint->methods = null; $metadata->addConstraint($constraint); } elseif ($constraint instanceof Constraint) { if (preg_match('/^(get|is)(.+)$/i', $method->name, $matches)) { $metadata->addGetterConstraint(lcfirst($matches[2]), $constraint); } else { throw new MappingException(sprintf('The constraint on "%s::%s" cannot be added. Constraints can only be added on methods beginning with "get" or "is".', $className, $method->name)); } } $loaded = true; } } } return $loaded; } } PK]t././#Validator/Mapping/ClassMetadata.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\ValidationVisitorInterface; use Symfony\Component\Validator\PropertyMetadataContainerInterface; use Symfony\Component\Validator\ClassBasedInterface; use Symfony\Component\Validator\MetadataInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\GroupDefinitionException; /** * Represents all the configured constraints on a given class. * * @author Bernhard Schussek * @author Fabien Potencier */ class ClassMetadata extends ElementMetadata implements MetadataInterface, ClassBasedInterface, PropertyMetadataContainerInterface { /** * @var string */ public $name; /** * @var string */ public $defaultGroup; /** * @var MemberMetadata[] */ public $members = array(); /** * @var PropertyMetadata[] */ public $properties = array(); /** * @var GetterMetadata[] */ public $getters = array(); /** * @var array */ public $groupSequence = array(); /** * @var Boolean */ public $groupSequenceProvider = false; /** * @var \ReflectionClass */ private $reflClass; /** * Constructs a metadata for the given class * * @param string $class */ public function __construct($class) { $this->name = $class; // class name without namespace if (false !== $nsSep = strrpos($class, '\\')) { $this->defaultGroup = substr($class, $nsSep + 1); } else { $this->defaultGroup = $class; } } public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null) { if (null === $propagatedGroup && Constraint::DEFAULT_GROUP === $group && ($this->hasGroupSequence() || $this->isGroupSequenceProvider())) { if ($this->hasGroupSequence()) { $groups = $this->getGroupSequence(); } else { $groups = $value->getGroupSequence(); } foreach ($groups as $group) { $this->accept($visitor, $value, $group, $propertyPath, Constraint::DEFAULT_GROUP); if (count($visitor->getViolations()) > 0) { break; } } return; } $visitor->visit($this, $value, $group, $propertyPath); if (null !== $value) { $pathPrefix = empty($propertyPath) ? '' : $propertyPath.'.'; foreach ($this->getConstrainedProperties() as $property) { foreach ($this->getMemberMetadatas($property) as $member) { $member->accept($visitor, $member->getPropertyValue($value), $group, $pathPrefix.$property, $propagatedGroup); } } } } /** * Returns the properties to be serialized * * @return array */ public function __sleep() { return array_merge(parent::__sleep(), array( 'getters', 'groupSequence', 'groupSequenceProvider', 'members', 'name', 'properties', 'defaultGroup' )); } /** * Returns the fully qualified name of the class * * @return string The fully qualified class name */ public function getClassName() { return $this->name; } /** * Returns the name of the default group for this class * * For each class, the group "Default" is an alias for the group * "", where is the non-namespaced name of the * class. All constraints implicitly or explicitly assigned to group * "Default" belong to both of these groups, unless the class defines * a group sequence. * * If a class defines a group sequence, validating the class in "Default" * will validate the group sequence. The constraints assigned to "Default" * can still be validated by validating the class in "". * * @return string The name of the default group */ public function getDefaultGroup() { return $this->defaultGroup; } /** * {@inheritDoc} */ public function addConstraint(Constraint $constraint) { if (!in_array(Constraint::CLASS_CONSTRAINT, (array) $constraint->getTargets())) { throw new ConstraintDefinitionException(sprintf( 'The constraint %s cannot be put on classes', get_class($constraint) )); } $constraint->addImplicitGroupName($this->getDefaultGroup()); parent::addConstraint($constraint); } /** * Adds a constraint to the given property. * * @param string $property The name of the property * @param Constraint $constraint The constraint * * @return ClassMetadata This object */ public function addPropertyConstraint($property, Constraint $constraint) { if (!isset($this->properties[$property])) { $this->properties[$property] = new PropertyMetadata($this->getClassName(), $property); $this->addMemberMetadata($this->properties[$property]); } $constraint->addImplicitGroupName($this->getDefaultGroup()); $this->properties[$property]->addConstraint($constraint); return $this; } /** * Adds a constraint to the getter of the given property. * * The name of the getter is assumed to be the name of the property with an * uppercased first letter and either the prefix "get" or "is". * * @param string $property The name of the property * @param Constraint $constraint The constraint * * @return ClassMetadata This object */ public function addGetterConstraint($property, Constraint $constraint) { if (!isset($this->getters[$property])) { $this->getters[$property] = new GetterMetadata($this->getClassName(), $property); $this->addMemberMetadata($this->getters[$property]); } $constraint->addImplicitGroupName($this->getDefaultGroup()); $this->getters[$property]->addConstraint($constraint); return $this; } /** * Merges the constraints of the given metadata into this object. * * @param ClassMetadata $source The source metadata */ public function mergeConstraints(ClassMetadata $source) { foreach ($source->getConstraints() as $constraint) { $this->addConstraint(clone $constraint); } foreach ($source->getConstrainedProperties() as $property) { foreach ($source->getMemberMetadatas($property) as $member) { $member = clone $member; foreach ($member->getConstraints() as $constraint) { $constraint->addImplicitGroupName($this->getDefaultGroup()); } $this->addMemberMetadata($member); if (!$member->isPrivate($this->name)) { $property = $member->getPropertyName(); if ($member instanceof PropertyMetadata && !isset($this->properties[$property])) { $this->properties[$property] = $member; } elseif ($member instanceof GetterMetadata && !isset($this->getters[$property])) { $this->getters[$property] = $member; } } } } } /** * Adds a member metadata. * * @param MemberMetadata $metadata */ protected function addMemberMetadata(MemberMetadata $metadata) { $property = $metadata->getPropertyName(); $this->members[$property][] = $metadata; } /** * Returns true if metadatas of members is present for the given property. * * @param string $property The name of the property * * @return Boolean */ public function hasMemberMetadatas($property) { return array_key_exists($property, $this->members); } /** * Returns all metadatas of members describing the given property. * * @param string $property The name of the property * * @return MemberMetadata[] An array of MemberMetadata */ public function getMemberMetadatas($property) { return $this->members[$property]; } /** * {@inheritdoc} */ public function hasPropertyMetadata($property) { return array_key_exists($property, $this->members); } /** * {@inheritdoc} */ public function getPropertyMetadata($property) { return $this->members[$property]; } /** * Returns all properties for which constraints are defined. * * @return array An array of property names */ public function getConstrainedProperties() { return array_keys($this->members); } /** * Sets the default group sequence for this class. * * @param array $groups An array of group names * * @return ClassMetadata * * @throws GroupDefinitionException */ public function setGroupSequence(array $groups) { if ($this->isGroupSequenceProvider()) { throw new GroupDefinitionException('Defining a static group sequence is not allowed with a group sequence provider'); } if (in_array(Constraint::DEFAULT_GROUP, $groups, true)) { throw new GroupDefinitionException(sprintf('The group "%s" is not allowed in group sequences', Constraint::DEFAULT_GROUP)); } if (!in_array($this->getDefaultGroup(), $groups, true)) { throw new GroupDefinitionException(sprintf('The group "%s" is missing in the group sequence', $this->getDefaultGroup())); } $this->groupSequence = $groups; return $this; } /** * Returns whether this class has an overridden default group sequence. * * @return Boolean */ public function hasGroupSequence() { return count($this->groupSequence) > 0; } /** * Returns the default group sequence for this class. * * @return array An array of group names */ public function getGroupSequence() { return $this->groupSequence; } /** * Returns a ReflectionClass instance for this class. * * @return \ReflectionClass */ public function getReflectionClass() { if (!$this->reflClass) { $this->reflClass = new \ReflectionClass($this->getClassName()); } return $this->reflClass; } /** * Sets whether a group sequence provider should be used. * * @param Boolean $active * * @throws GroupDefinitionException */ public function setGroupSequenceProvider($active) { if ($this->hasGroupSequence()) { throw new GroupDefinitionException('Defining a group sequence provider is not allowed with a static group sequence'); } if (!$this->getReflectionClass()->implementsInterface('Symfony\Component\Validator\GroupSequenceProviderInterface')) { throw new GroupDefinitionException(sprintf('Class "%s" must implement GroupSequenceProviderInterface', $this->name)); } $this->groupSequenceProvider = $active; } /** * Returns whether the class is a group sequence provider. * * @return Boolean */ public function isGroupSequenceProvider() { return $this->groupSequenceProvider; } } PK]$Validator/Mapping/Cache/ApcCache.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Cache; use Symfony\Component\Validator\Mapping\ClassMetadata; class ApcCache implements CacheInterface { private $prefix; public function __construct($prefix) { if (!extension_loaded('apc')) { throw new \RuntimeException('Unable to use ApcCache to cache validator mappings as APC is not enabled.'); } $this->prefix = $prefix; } public function has($class) { if (!function_exists('apc_exists')) { $exists = false; apc_fetch($this->prefix.$class, $exists); return $exists; } return apc_exists($this->prefix.$class); } public function read($class) { return apc_fetch($this->prefix.$class); } public function write(ClassMetadata $metadata) { apc_store($this->prefix.$metadata->getClassName(), $metadata); } } PK]+d%%*Validator/Mapping/Cache/CacheInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Cache; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * Persists ClassMetadata instances in a cache * * @author Bernhard Schussek */ interface CacheInterface { /** * Returns whether metadata for the given class exists in the cache * * @param string $class */ public function has($class); /** * Returns the metadata for the given class from the cache * * @param string $class Class Name * * @return ClassMetadata|false A ClassMetadata instance or false on miss */ public function read($class); /** * Stores a class metadata in the cache * * @param ClassMetadata $metadata A Class Metadata */ public function write(ClassMetadata $metadata); } PK]|$Validator/Mapping/GetterMetadata.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Exception\ValidatorException; class GetterMetadata extends MemberMetadata { /** * Constructor. * * @param string $class The class the getter is defined on * @param string $property The property which the getter returns * * @throws ValidatorException */ public function __construct($class, $property) { $getMethod = 'get'.ucfirst($property); $isMethod = 'is'.ucfirst($property); if (method_exists($class, $getMethod)) { $method = $getMethod; } elseif (method_exists($class, $isMethod)) { $method = $isMethod; } else { throw new ValidatorException(sprintf('Neither method %s nor %s exists in class %s', $getMethod, $isMethod, $class)); } parent::__construct($class, $method, $property); } /** * {@inheritDoc} */ public function getPropertyValue($object) { return $this->newReflectionMember($object)->invoke($object); } /** * {@inheritDoc} */ protected function newReflectionMember($objectOrClassName) { return new \ReflectionMethod($objectOrClassName, $this->getName()); } } PK]L8 (Validator/ValidationVisitorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Validates values against constraints defined in {@link MetadataInterface} * instances. * * This interface is an implementation of the Visitor design pattern. A value * is validated by first passing it to the {@link validate} method. That method * will determine the matching {@link MetadataInterface} for validating the * value. It then calls the {@link MetadataInterface::accept} method of that * metadata. accept() does two things: * *
    *
  1. It calls {@link visit} to validate the value against the constraints of * the metadata.
  2. *
  3. It calls accept() on all nested metadata instances with the * corresponding values extracted from the current value. For example, if the * current metadata represents a class and the current value is an object of * that class, the metadata contains nested instances for each property of that * class. It forwards the call to these nested metadata with the values of the * corresponding properties in the original object.
  4. *
* * @author Bernhard Schussek */ interface ValidationVisitorInterface { /** * Validates a value. * * If the value is an array or a traversable object, you can set the * parameter $traverse to true in order to run through * the collection and validate each element. If these elements can be * collections again and you want to traverse them recursively, set the * parameter $deep to true as well. * * If you set $traversable to true, the visitor will * nevertheless try to find metadata for the collection and validate its * constraints. If no such metadata is found, the visitor ignores that and * only iterates the collection. * * If you don't set $traversable to true and the visitor * does not find metadata for the given value, it will fail with an * exception. * * @param mixed $value The value to validate. * @param string $group The validation group to validate. * @param string $propertyPath The current property path in the validation graph. * @param Boolean $traverse Whether to traverse the value if it is traversable. * @param Boolean $deep Whether to traverse nested traversable values recursively. * * @throws Exception\NoSuchMetadataException If no metadata can be found for * the given value. */ public function validate($value, $group, $propertyPath, $traverse = false, $deep = false); /** * Validates a value against the constraints defined in some metadata. * * This method implements the Visitor design pattern. See also * {@link ValidationVisitorInterface}. * * @param MetadataInterface $metadata The metadata holding the constraints. * @param mixed $value The value to validate. * @param string $group The validation group to validate. * @param string $propertyPath The current property path in the validation graph. */ public function visit(MetadataInterface $metadata, $value, $group, $propertyPath); } PK] Sb'b'Validator/ValidatorBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Validator\Mapping\ClassMetadataFactory; use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Validator\Mapping\Loader\LoaderChain; use Symfony\Component\Validator\Mapping\Cache\CacheInterface; use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader; use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; use Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader; use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; use Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader; use Symfony\Component\Translation\TranslatorInterface; use Doctrine\Common\Annotations\Reader; use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\CachedReader; use Doctrine\Common\Cache\ArrayCache; /** * The default implementation of {@link ValidatorBuilderInterface}. * * @author Bernhard Schussek */ class ValidatorBuilder implements ValidatorBuilderInterface { /** * @var array */ private $initializers = array(); /** * @var array */ private $xmlMappings = array(); /** * @var array */ private $yamlMappings = array(); /** * @var array */ private $methodMappings = array(); /** * @var Reader */ private $annotationReader = null; /** * @var MetadataFactoryInterface */ private $metadataFactory; /** * @var ConstraintValidatorFactoryInterface */ private $validatorFactory; /** * @var CacheInterface */ private $metadataCache; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var PropertyAccessorInterface */ private $propertyAccessor; /** * {@inheritdoc} */ public function addObjectInitializer(ObjectInitializerInterface $initializer) { $this->initializers[] = $initializer; return $this; } /** * {@inheritdoc} */ public function addObjectInitializers(array $initializers) { $this->initializers = array_merge($this->initializers, $initializers); return $this; } /** * {@inheritdoc} */ public function addXmlMapping($path) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->xmlMappings[] = $path; return $this; } /** * {@inheritdoc} */ public function addXmlMappings(array $paths) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->xmlMappings = array_merge($this->xmlMappings, $paths); return $this; } /** * {@inheritdoc} */ public function addYamlMapping($path) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->yamlMappings[] = $path; return $this; } /** * {@inheritdoc} */ public function addYamlMappings(array $paths) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->yamlMappings = array_merge($this->yamlMappings, $paths); return $this; } /** * {@inheritdoc} */ public function addMethodMapping($methodName) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->methodMappings[] = $methodName; return $this; } /** * {@inheritdoc} */ public function addMethodMappings(array $methodNames) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->methodMappings = array_merge($this->methodMappings, $methodNames); return $this; } /** * {@inheritdoc} */ public function enableAnnotationMapping(Reader $annotationReader = null) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot enable annotation mapping after setting a custom metadata factory. Configure your metadata factory instead.'); } if (null === $annotationReader) { if (!class_exists('Doctrine\Common\Annotations\AnnotationReader') || !class_exists('Doctrine\Common\Cache\ArrayCache')) { throw new \RuntimeException('Enabling annotation based constraint mapping requires the packages doctrine/annotations and doctrine/cache to be installed.'); } $annotationReader = new CachedReader(new AnnotationReader(), new ArrayCache()); } $this->annotationReader = $annotationReader; return $this; } /** * {@inheritdoc} */ public function disableAnnotationMapping() { $this->annotationReader = null; return $this; } /** * {@inheritdoc} */ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory) { if (count($this->xmlMappings) > 0 || count($this->yamlMappings) > 0 || count($this->methodMappings) > 0 || null !== $this->annotationReader) { throw new ValidatorException('You cannot set a custom metadata factory after adding custom mappings. You should do either of both.'); } $this->metadataFactory = $metadataFactory; return $this; } /** * {@inheritdoc} */ public function setMetadataCache(CacheInterface $cache) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot set a custom metadata cache after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->metadataCache = $cache; return $this; } /** * {@inheritdoc} */ public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory) { if (null !== $this->propertyAccessor) { throw new ValidatorException('You cannot set a validator factory after setting a custom property accessor. Remove the call to setPropertyAccessor() if you want to call setConstraintValidatorFactory().'); } $this->validatorFactory = $validatorFactory; return $this; } /** * {@inheritdoc} */ public function setTranslator(TranslatorInterface $translator) { $this->translator = $translator; return $this; } /** * {@inheritdoc} */ public function setTranslationDomain($translationDomain) { $this->translationDomain = $translationDomain; return $this; } /** * {@inheritdoc} */ public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor) { if (null !== $this->validatorFactory) { throw new ValidatorException('You cannot set a property accessor after setting a custom validator factory. Configure your validator factory instead.'); } $this->propertyAccessor = $propertyAccessor; return $this; } /** * {@inheritdoc} */ public function getValidator() { $metadataFactory = $this->metadataFactory; if (!$metadataFactory) { $loaders = array(); if (count($this->xmlMappings) > 1) { $loaders[] = new XmlFilesLoader($this->xmlMappings); } elseif (1 === count($this->xmlMappings)) { $loaders[] = new XmlFileLoader($this->xmlMappings[0]); } if (count($this->yamlMappings) > 1) { $loaders[] = new YamlFilesLoader($this->yamlMappings); } elseif (1 === count($this->yamlMappings)) { $loaders[] = new YamlFileLoader($this->yamlMappings[0]); } foreach ($this->methodMappings as $methodName) { $loaders[] = new StaticMethodLoader($methodName); } if ($this->annotationReader) { $loaders[] = new AnnotationLoader($this->annotationReader); } $loader = null; if (count($loaders) > 1) { $loader = new LoaderChain($loaders); } elseif (1 === count($loaders)) { $loader = $loaders[0]; } $metadataFactory = new ClassMetadataFactory($loader, $this->metadataCache); } $propertyAccessor = $this->propertyAccessor ?: PropertyAccess::createPropertyAccessor(); $validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory($propertyAccessor); $translator = $this->translator ?: new DefaultTranslator(); return new Validator($metadataFactory, $validatorFactory, $translator, $this->translationDomain, $this->initializers); } } PK]C0C0'Validator/ExecutionContextInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Stores the validator's state during validation. * * For example, let's validate the following object graph: * *
 * (Person)---($firstName: string)
 *      \
 *   ($address: Address)---($street: string)
 * 
* * We validate the Person instance, which becomes the "root" of the * validation run (see {@link getRoot}). The state of the context after the * first step will be like this: * *
 * (Person)---($firstName: string)
 *    ^ \
 *   ($address: Address)---($street: string)
 * 
* * The validator is stopped at the Person node, both the root and the * value (see {@link getValue}) of the context point to the Person * instance. The property path is empty at this point (see {@link getPropertyPath}). * The metadata of the context is the metadata of the Person node * (see {@link getMetadata}). * * After advancing to the property $firstName of the Person * instance, the state of the context looks like this: * *
 * (Person)---($firstName: string)
 *      \              ^
 *   ($address: Address)---($street: string)
 * 
* * The validator is stopped at the property $firstName. The root still * points to the Person instance, because this is where the validation * started. The property path is now "firstName" and the current value is the * value of that property. * * After advancing to the $address property and then to the * $street property of the Address instance, the context state * looks like this: * *
 * (Person)---($firstName: string)
 *      \
 *   ($address: Address)---($street: string)
 *                               ^
 * 
* * The validator is stopped at the property $street. The root still * points to the Person instance, but the property path is now * "address.street" and the validated value is the value of that property. * * Apart from the root, the property path and the currently validated value, * the execution context also knows the metadata of the current node (see * {@link getMetadata}) which for example returns a {@link Mapping\PropertyMetadata} * or a {@link Mapping\ClassMetadata} object. he context also contains the * validation group that is currently being validated (see {@link getGroup}) and * the violations that happened up until now (see {@link getViolations}). * * Apart from reading the execution context, you can also use * {@link addViolation} or {@link addViolationAt} to add new violations and * {@link validate} or {@link validateValue} to validate values that the * validator otherwise would not reach. * * @author Bernhard Schussek * * @api */ interface ExecutionContextInterface { /** * Adds a violation at the current node of the validation graph. * * @param string $message The error message. * @param array $params The parameters substituted in the error message. * @param mixed $invalidValue The invalid, validated value. * @param integer|null $pluralization The number to use to pluralize of the message. * @param integer|null $code The violation code. * * @api */ public function addViolation($message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null); /** * Adds a violation at the validation graph node with the given property * path relative to the current property path. * * @param string $subPath The relative property path for the violation. * @param string $message The error message. * @param array $params The parameters substituted in the error message. * @param mixed $invalidValue The invalid, validated value. * @param integer|null $pluralization The number to use to pluralize of the message. * @param integer|null $code The violation code. * * @api */ public function addViolationAt($subPath, $message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null); /** * Validates the given value within the scope of the current validation. * * The value may be any value recognized by the used metadata factory * (see {@link MetadataFactoryInterface::getMetadata}), or an array or a * traversable object of such values. * * Usually you validate a value that is not the current node of the * execution context. For this case, you can pass the {@link $subPath} * argument which is appended to the current property path when a violation * is created. For example, take the following object graph: * *
     * (Person)---($address: Address)---($phoneNumber: PhoneNumber)
     *                     ^
     * 
* * When the execution context stops at the Person instance, the * property path is "address". When you validate the PhoneNumber * instance now, pass "phoneNumber" as sub path to correct the property path * to "address.phoneNumber": * *
     * $context->validate($address->phoneNumber, 'phoneNumber');
     * 
* * Any violations generated during the validation will be added to the * violation list that you can access with {@link getViolations}. * * @param mixed $value The value to validate. * @param string $subPath The path to append to the context's property path. * @param null|string|string[] $groups The groups to validate in. If you don't pass any * groups here, the current group of the context * will be used. * @param Boolean $traverse Whether to traverse the value if it is an array * or an instance of \Traversable. * @param Boolean $deep Whether to traverse the value recursively if * it is a collection of collections. */ public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false); /** * Validates a value against a constraint. * * Use the parameter $subPath to adapt the property path for the * validated value. For example, take the following object graph: * *
     * (Person)---($address: Address)---($street: string)
     *                     ^
     * 
* * When the validator validates the Address instance, the * property path stored in the execution context is "address". When you * manually validate the property $street now, pass the sub path * "street" to adapt the full property path to "address.street": * *
     * $context->validate($address->street, new NotNull(), 'street');
     * 
* * @param mixed $value The value to validate. * @param Constraint|Constraint[] $constraints The constraint(s) to validate against. * @param string $subPath The path to append to the context's property path. * @param null|string|string[] $groups The groups to validate in. If you don't pass any * groups here, the current group of the context * will be used. */ public function validateValue($value, $constraints, $subPath = '', $groups = null); /** * Returns the violations generated by the validator so far. * * @return ConstraintViolationListInterface The constraint violation list. * * @api */ public function getViolations(); /** * Returns the value at which validation was started in the object graph. * * The validator, when given an object, traverses the properties and * related objects and their properties. The root of the validation is the * object from which the traversal started. * * The current value is returned by {@link getValue}. * * @return mixed The root value of the validation. */ public function getRoot(); /** * Returns the value that the validator is currently validating. * * If you want to retrieve the object that was originally passed to the * validator, use {@link getRoot}. * * @return mixed The currently validated value. */ public function getValue(); /** * Returns the metadata for the currently validated value. * * With the core implementation, this method returns a * {@link Mapping\ClassMetadata} instance if the current value is an object, * a {@link Mapping\PropertyMetadata} instance if the current value is * the value of a property and a {@link Mapping\GetterMetadata} instance if * the validated value is the result of a getter method. * * If the validated value is neither of these, for example if the validator * has been called with a plain value and constraint, this method returns * null. * * @return MetadataInterface|null The metadata of the currently validated * value. */ public function getMetadata(); /** * Returns the used metadata factory. * * @return MetadataFactoryInterface The metadata factory. */ public function getMetadataFactory(); /** * Returns the validation group that is currently being validated. * * @return string The current validation group. */ public function getGroup(); /** * Returns the class name of the current node. * * If the metadata of the current node does not implement * {@link ClassBasedInterface} or if no metadata is available for the * current node, this method returns null. * * @return string|null The class name or null, if no class name could be found. */ public function getClassName(); /** * Returns the property name of the current node. * * If the metadata of the current node does not implement * {@link PropertyMetadataInterface} or if no metadata is available for the * current node, this method returns null. * * @return string|null The property name or null, if no property name could be found. */ public function getPropertyName(); /** * Returns the property path to the value that the validator is currently * validating. * * For example, take the following object graph: * *
     * (Person)---($address: Address)---($street: string)
     * 
* * When the Person instance is passed to the validator, the * property path is initially empty. When the $address property * of that person is validated, the property path is "address". When * the $street property of the related Address instance * is validated, the property path is "address.street". * * Properties of objects are prefixed with a dot in the property path. * Indices of arrays or objects implementing the {@link \ArrayAccess} * interface are enclosed in brackets. For example, if the property in * the previous example is $addresses and contains an array * of Address instance, the property path generated for the * $street property of one of these addresses is for example * "addresses[0].street". * * @param string $subPath Optional. The suffix appended to the current * property path. * * @return string The current property path. The result may be an empty * string if the validator is currently validating the * root value of the validation graph. */ public function getPropertyPath($subPath = ''); } PK]dValidator/Validator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Translation\TranslatorInterface; /** * Default implementation of {@link ValidatorInterface}. * * @author Fabien Potencier * @author Bernhard Schussek */ class Validator implements ValidatorInterface { /** * @var MetadataFactoryInterface */ private $metadataFactory; /** * @var ConstraintValidatorFactoryInterface */ private $validatorFactory; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var array */ private $objectInitializers; public function __construct( MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = 'validators', array $objectInitializers = array() ) { $this->metadataFactory = $metadataFactory; $this->validatorFactory = $validatorFactory; $this->translator = $translator; $this->translationDomain = $translationDomain; $this->objectInitializers = $objectInitializers; } /** * {@inheritdoc} */ public function getMetadataFactory() { return $this->metadataFactory; } /** * {@inheritDoc} */ public function getMetadataFor($value) { return $this->metadataFactory->getMetadataFor($value); } /** * {@inheritDoc} */ public function validate($value, $groups = null, $traverse = false, $deep = false) { $visitor = $this->createVisitor($value); foreach ($this->resolveGroups($groups) as $group) { $visitor->validate($value, $group, '', $traverse, $deep); } return $visitor->getViolations(); } /** * {@inheritDoc} * * @throws ValidatorException If the metadata for the value does not support properties. */ public function validateProperty($containingValue, $property, $groups = null) { $visitor = $this->createVisitor($containingValue); $metadata = $this->metadataFactory->getMetadataFor($containingValue); if (!$metadata instanceof PropertyMetadataContainerInterface) { $valueAsString = is_scalar($containingValue) ? '"'.$containingValue.'"' : 'the value of type '.gettype($containingValue); throw new ValidatorException(sprintf('The metadata for %s does not support properties.', $valueAsString)); } foreach ($this->resolveGroups($groups) as $group) { if (!$metadata->hasPropertyMetadata($property)) { continue; } foreach ($metadata->getPropertyMetadata($property) as $propMeta) { $propMeta->accept($visitor, $propMeta->getPropertyValue($containingValue), $group, $property); } } return $visitor->getViolations(); } /** * {@inheritDoc} * * @throws ValidatorException If the metadata for the value does not support properties. */ public function validatePropertyValue($containingValue, $property, $value, $groups = null) { $visitor = $this->createVisitor($containingValue); $metadata = $this->metadataFactory->getMetadataFor($containingValue); if (!$metadata instanceof PropertyMetadataContainerInterface) { $valueAsString = is_scalar($containingValue) ? '"'.$containingValue.'"' : 'the value of type '.gettype($containingValue); throw new ValidatorException(sprintf('The metadata for '.$valueAsString.' does not support properties.')); } foreach ($this->resolveGroups($groups) as $group) { if (!$metadata->hasPropertyMetadata($property)) { continue; } foreach ($metadata->getPropertyMetadata($property) as $propMeta) { $propMeta->accept($visitor, $value, $group, $property); } } return $visitor->getViolations(); } /** * {@inheritDoc} */ public function validateValue($value, $constraints, $groups = null) { $context = new ExecutionContext($this->createVisitor($value), $this->translator, $this->translationDomain); $constraints = is_array($constraints) ? $constraints : array($constraints); foreach ($constraints as $constraint) { if ($constraint instanceof Valid) { // Why can't the Valid constraint be executed directly? // // It cannot be executed like regular other constraints, because regular // constraints are only executed *if they belong to the validated group*. // The Valid constraint, on the other hand, is always executed and propagates // the group to the cascaded object. The propagated group depends on // // * Whether a group sequence is currently being executed. Then the default // group is propagated. // // * Otherwise the validated group is propagated. throw new ValidatorException( sprintf( 'The constraint %s cannot be validated. Use the method validate() instead.', get_class($constraint) ) ); } $context->validateValue($value, $constraint, '', $groups); } return $context->getViolations(); } /** * @param mixed $root * * @return ValidationVisitor */ private function createVisitor($root) { return new ValidationVisitor( $root, $this->metadataFactory, $this->validatorFactory, $this->translator, $this->translationDomain, $this->objectInitializers ); } /** * @param null|string|string[] $groups * * @return string[] */ private function resolveGroups($groups) { return $groups ? (array) $groups : array(Constraint::DEFAULT_GROUP); } } PK]oSSValidator/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A list of constraint violations. * * @author Bernhard Schussek * * @api */ interface ConstraintViolationListInterface extends \Traversable, \Countable, \ArrayAccess { /** * Adds a constraint violation to this list. * * @param ConstraintViolationInterface $violation The violation to add. * * @api */ public function add(ConstraintViolationInterface $violation); /** * Merges an existing violation list into this list. * * @param ConstraintViolationListInterface $otherList The list to merge. * * @api */ public function addAll(ConstraintViolationListInterface $otherList); /** * Returns the violation at a given offset. * * @param integer $offset The offset of the violation. * * @return ConstraintViolationInterface The violation. * * @throws \OutOfBoundsException If the offset does not exist. * * @api */ public function get($offset); /** * Returns whether the given offset exists. * * @param integer $offset The violation offset. * * @return Boolean Whether the offset exists. * * @api */ public function has($offset); /** * Sets a violation at a given offset. * * @param integer $offset The violation offset. * @param ConstraintViolationInterface $violation The violation. * * @api */ public function set($offset, ConstraintViolationInterface $violation); /** * Removes a violation at a given offset. * * @param integer $offset The offset to remove. * * @api */ public function remove($offset); } PK]Nm1EventDispatcher/ContainerAwareEventDispatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Lazily loads listeners and subscribers from the dependency injection * container * * @author Fabien Potencier * @author Bernhard Schussek * @author Jordan Alliot */ class ContainerAwareEventDispatcher extends EventDispatcher { /** * The container from where services are loaded * @var ContainerInterface */ private $container; /** * The service IDs of the event listeners and subscribers * @var array */ private $listenerIds = array(); /** * The services registered as listeners * @var array */ private $listeners = array(); /** * Constructor. * * @param ContainerInterface $container A ContainerInterface instance */ public function __construct(ContainerInterface $container) { $this->container = $container; } /** * Adds a service as event listener * * @param string $eventName Event for which the listener is added * @param array $callback The service ID of the listener service & the method * name that has to be called * @param integer $priority The higher this value, the earlier an event listener * will be triggered in the chain. * Defaults to 0. * * @throws \InvalidArgumentException */ public function addListenerService($eventName, $callback, $priority = 0) { if (!is_array($callback) || 2 !== count($callback)) { throw new \InvalidArgumentException('Expected an array("service", "method") argument'); } $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority); } public function removeListener($eventName, $listener) { $this->lazyLoad($eventName); if (isset($this->listeners[$eventName])) { foreach ($this->listeners[$eventName] as $key => $l) { foreach ($this->listenerIds[$eventName] as $i => $args) { list($serviceId, $method, $priority) = $args; if ($key === $serviceId.'.'.$method) { if ($listener === array($l, $method)) { unset($this->listeners[$eventName][$key]); if (empty($this->listeners[$eventName])) { unset($this->listeners[$eventName]); } unset($this->listenerIds[$eventName][$i]); if (empty($this->listenerIds[$eventName])) { unset($this->listenerIds[$eventName]); } } } } } } parent::removeListener($eventName, $listener); } /** * @see EventDispatcherInterface::hasListeners */ public function hasListeners($eventName = null) { if (null === $eventName) { return (Boolean) count($this->listenerIds) || (Boolean) count($this->listeners); } if (isset($this->listenerIds[$eventName])) { return true; } return parent::hasListeners($eventName); } /** * @see EventDispatcherInterface::getListeners */ public function getListeners($eventName = null) { if (null === $eventName) { foreach (array_keys($this->listenerIds) as $serviceEventName) { $this->lazyLoad($serviceEventName); } } else { $this->lazyLoad($eventName); } return parent::getListeners($eventName); } /** * Adds a service as event subscriber * * @param string $serviceId The service ID of the subscriber service * @param string $class The service's class name (which must implement EventSubscriberInterface) */ public function addSubscriberService($serviceId, $class) { foreach ($class::getSubscribedEvents() as $eventName => $params) { if (is_string($params)) { $this->listenerIds[$eventName][] = array($serviceId, $params, 0); } elseif (is_string($params[0])) { $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0); } else { foreach ($params as $listener) { $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0); } } } } /** * {@inheritDoc} * * Lazily loads listeners for this event from the dependency injection * container. * * @throws \InvalidArgumentException if the service is not defined */ public function dispatch($eventName, Event $event = null) { $this->lazyLoad($eventName); return parent::dispatch($eventName, $event); } public function getContainer() { return $this->container; } /** * Lazily loads listeners for this event from the dependency injection * container. * * @param string $eventName The name of the event to dispatch. The name of * the event is the name of the method that is * invoked on listeners. */ protected function lazyLoad($eventName) { if (isset($this->listenerIds[$eventName])) { foreach ($this->listenerIds[$eventName] as $args) { list($serviceId, $method, $priority) = $args; $listener = $this->container->get($serviceId); $key = $serviceId.'.'.$method; if (!isset($this->listeners[$eventName][$key])) { $this->addListener($eventName, array($listener, $method), $priority); } elseif ($listener !== $this->listeners[$eventName][$key]) { parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method)); $this->addListener($eventName, array($listener, $method), $priority); } $this->listeners[$eventName][$key] = $listener; } } } } PK]bk EventDispatcher/Event.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * Event is the base class for classes containing event data. * * This class contains no event data. It is used by events that do not pass * state information to an event handler when an event is raised. * * You can call the method stopPropagation() to abort the execution of * further listeners in your event listener. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek * * @api */ class Event { /** * @var Boolean Whether no further event listeners should be triggered */ private $propagationStopped = false; /** * @var EventDispatcher Dispatcher that dispatched this event */ private $dispatcher; /** * @var string This event's name */ private $name; /** * Returns whether further event listeners should be triggered. * * @see Event::stopPropagation * @return Boolean Whether propagation was already stopped for this event. * * @api */ public function isPropagationStopped() { return $this->propagationStopped; } /** * Stops the propagation of the event to further event listeners. * * If multiple event listeners are connected to the same event, no * further event listener will be triggered once any trigger calls * stopPropagation(). * * @api */ public function stopPropagation() { $this->propagationStopped = true; } /** * Stores the EventDispatcher that dispatches this Event * * @param EventDispatcherInterface $dispatcher * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call. * * @api */ public function setDispatcher(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } /** * Returns the EventDispatcher that dispatches this Event * * @return EventDispatcherInterface * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call. * * @api */ public function getDispatcher() { return $this->dispatcher; } /** * Gets the event's name. * * @return string * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call. * * @api */ public function getName() { return $this->name; } /** * Sets the event's name property. * * @param string $name The event name. * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call. * * @api */ public function setName($name) { $this->name = $name; } } PK]s ,EventDispatcher/ImmutableEventDispatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * A read-only proxy for an event dispatcher. * * @author Bernhard Schussek */ class ImmutableEventDispatcher implements EventDispatcherInterface { /** * The proxied dispatcher. * @var EventDispatcherInterface */ private $dispatcher; /** * Creates an unmodifiable proxy for an event dispatcher. * * @param EventDispatcherInterface $dispatcher The proxied event dispatcher. */ public function __construct(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } /** * {@inheritdoc} */ public function dispatch($eventName, Event $event = null) { return $this->dispatcher->dispatch($eventName, $event); } /** * {@inheritdoc} */ public function addListener($eventName, $listener, $priority = 0) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function addSubscriber(EventSubscriberInterface $subscriber) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function removeListener($eventName, $listener) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function removeSubscriber(EventSubscriberInterface $subscriber) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function getListeners($eventName = null) { return $this->dispatcher->getListeners($eventName); } /** * {@inheritdoc} */ public function hasListeners($eventName = null) { return $this->dispatcher->hasListeners($eventName); } } PK]cG11,EventDispatcher/EventSubscriberInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * An EventSubscriber knows himself what events he is interested in. * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes * {@link getSubscribedEvents} and registers the subscriber as a listener for all * returned events. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek * * @api */ interface EventSubscriberInterface { /** * Returns an array of event names this subscriber wants to listen to. * * The array keys are event names and the value can be: * * * The method name to call (priority defaults to 0) * * An array composed of the method name to call and the priority * * An array of arrays composed of the method names to call and respective * priorities, or 0 if unset * * For instance: * * * array('eventName' => 'methodName') * * array('eventName' => array('methodName', $priority)) * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) * * @return array The event names to listen to * * @api */ public static function getSubscribedEvents(); } PK]Y"#EventDispatcher/EventDispatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * * Listeners are registered on the manager and events are dispatched through the * manager. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek * @author Fabien Potencier * @author Jordi Boggiano * @author Jordan Alliot * * @api */ class EventDispatcher implements EventDispatcherInterface { private $listeners = array(); private $sorted = array(); /** * @see EventDispatcherInterface::dispatch * * @api */ public function dispatch($eventName, Event $event = null) { if (null === $event) { $event = new Event(); } $event->setDispatcher($this); $event->setName($eventName); if (!isset($this->listeners[$eventName])) { return $event; } $this->doDispatch($this->getListeners($eventName), $eventName, $event); return $event; } /** * @see EventDispatcherInterface::getListeners */ public function getListeners($eventName = null) { if (null !== $eventName) { if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } return $this->sorted[$eventName]; } foreach (array_keys($this->listeners) as $eventName) { if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } } return $this->sorted; } /** * @see EventDispatcherInterface::hasListeners */ public function hasListeners($eventName = null) { return (Boolean) count($this->getListeners($eventName)); } /** * @see EventDispatcherInterface::addListener * * @api */ public function addListener($eventName, $listener, $priority = 0) { $this->listeners[$eventName][$priority][] = $listener; unset($this->sorted[$eventName]); } /** * @see EventDispatcherInterface::removeListener */ public function removeListener($eventName, $listener) { if (!isset($this->listeners[$eventName])) { return; } foreach ($this->listeners[$eventName] as $priority => $listeners) { if (false !== ($key = array_search($listener, $listeners, true))) { unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]); } } } /** * @see EventDispatcherInterface::addSubscriber * * @api */ public function addSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (is_string($params)) { $this->addListener($eventName, array($subscriber, $params)); } elseif (is_string($params[0])) { $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0); } else { foreach ($params as $listener) { $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0); } } } } /** * @see EventDispatcherInterface::removeSubscriber */ public function removeSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (is_array($params) && is_array($params[0])) { foreach ($params as $listener) { $this->removeListener($eventName, array($subscriber, $listener[0])); } } else { $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0])); } } } /** * Triggers the listeners of an event. * * This method can be overridden to add functionality that is executed * for each listener. * * @param callable[] $listeners The event listeners. * @param string $eventName The name of the event to dispatch. * @param Event $event The event object to pass to the event handlers/listeners. */ protected function doDispatch($listeners, $eventName, Event $event) { foreach ($listeners as $listener) { call_user_func($listener, $event, $eventName, $this); if ($event->isPropagationStopped()) { break; } } } /** * Sorts the internal list of listeners for the given event by priority. * * @param string $eventName The name of the event. */ private function sortListeners($eventName) { $this->sorted[$eventName] = array(); if (isset($this->listeners[$eventName])) { krsort($this->listeners[$eventName]); $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); } } } PK]U ,EventDispatcher/EventDispatcherInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * Listeners are registered on the manager and events are dispatched through the * manager. * * @author Bernhard Schussek * * @api */ interface EventDispatcherInterface { /** * Dispatches an event to all registered listeners. * * @param string $eventName The name of the event to dispatch. The name of * the event is the name of the method that is * invoked on listeners. * @param Event $event The event to pass to the event handlers/listeners. * If not supplied, an empty Event instance is created. * * @return Event * * @api */ public function dispatch($eventName, Event $event = null); /** * Adds an event listener that listens on the specified events. * * @param string $eventName The event to listen on * @param callable $listener The listener * @param integer $priority The higher this value, the earlier an event * listener will be triggered in the chain (defaults to 0) * * @api */ public function addListener($eventName, $listener, $priority = 0); /** * Adds an event subscriber. * * The subscriber is asked for all the events he is * interested in and added as a listener for these events. * * @param EventSubscriberInterface $subscriber The subscriber. * * @api */ public function addSubscriber(EventSubscriberInterface $subscriber); /** * Removes an event listener from the specified events. * * @param string|array $eventName The event(s) to remove a listener from * @param callable $listener The listener to remove */ public function removeListener($eventName, $listener); /** * Removes an event subscriber. * * @param EventSubscriberInterface $subscriber The subscriber */ public function removeSubscriber(EventSubscriberInterface $subscriber); /** * Gets the listeners of a specific event or all listeners. * * @param string $eventName The name of the event * * @return array The event listeners for the specified event, or all event listeners by event name */ public function getListeners($eventName = null); /** * Checks whether an event has any registered listeners. * * @param string $eventName The name of the event * * @return Boolean true if the specified event has any listeners, false otherwise */ public function hasListeners($eventName = null); } PK],DD EventDispatcher/GenericEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * Event encapsulation class. * * Encapsulates events thus decoupling the observer from the subject they encapsulate. * * @author Drak */ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate { /** * Event subject. * * @var mixed usually object or callable */ protected $subject; /** * Array of arguments. * * @var array */ protected $arguments; /** * Encapsulate an event with $subject and $args. * * @param mixed $subject The subject of the event, usually an object. * @param array $arguments Arguments to store in the event. */ public function __construct($subject = null, array $arguments = array()) { $this->subject = $subject; $this->arguments = $arguments; } /** * Getter for subject property. * * @return mixed $subject The observer subject. */ public function getSubject() { return $this->subject; } /** * Get argument by key. * * @param string $key Key. * * @throws \InvalidArgumentException If key is not found. * * @return mixed Contents of array key. */ public function getArgument($key) { if ($this->hasArgument($key)) { return $this->arguments[$key]; } throw new \InvalidArgumentException(sprintf('%s not found in %s', $key, $this->getName())); } /** * Add argument to event. * * @param string $key Argument name. * @param mixed $value Value. * * @return GenericEvent */ public function setArgument($key, $value) { $this->arguments[$key] = $value; return $this; } /** * Getter for all arguments. * * @return array */ public function getArguments() { return $this->arguments; } /** * Set args property. * * @param array $args Arguments. * * @return GenericEvent */ public function setArguments(array $args = array()) { $this->arguments = $args; return $this; } /** * Has argument. * * @param string $key Key of arguments array. * * @return boolean */ public function hasArgument($key) { return array_key_exists($key, $this->arguments); } /** * ArrayAccess for argument getter. * * @param string $key Array key. * * @throws \InvalidArgumentException If key does not exist in $this->args. * * @return mixed */ public function offsetGet($key) { return $this->getArgument($key); } /** * ArrayAccess for argument setter. * * @param string $key Array key to set. * @param mixed $value Value. */ public function offsetSet($key, $value) { $this->setArgument($key, $value); } /** * ArrayAccess for unset argument. * * @param string $key Array key. */ public function offsetUnset($key) { if ($this->hasArgument($key)) { unset($this->arguments[$key]); } } /** * ArrayAccess has argument. * * @param string $key Array key. * * @return boolean */ public function offsetExists($key) { return $this->hasArgument($key); } /** * IteratorAggregate for iterating over the object like an array * * @return \ArrayIterator */ public function getIterator() { return new \ArrayIterator($this->arguments); } } PK] ;EventDispatcher/Debug/TraceableEventDispatcherInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher\Debug; /** * @author Fabien Potencier */ interface TraceableEventDispatcherInterface { /** * Gets the called listeners. * * @return array An array of called listeners */ public function getCalledListeners(); /** * Gets the not called listeners. * * @return array An array of not called listeners */ public function getNotCalledListeners(); } PK] YYEventDispatcher/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler; /** * Link represents an HTML link (an HTML a or area tag). * * @author Fabien Potencier * * @api */ class Link { /** * @var \DOMNode A \DOMNode instance */ protected $node; /** * @var string The method to use for the link */ protected $method; /** * @var string The URI of the page where the link is embedded (or the base href) */ protected $currentUri; /** * Constructor. * * @param \DOMNode $node A \DOMNode instance * @param string $currentUri The URI of the page where the link is embedded (or the base href) * @param string $method The method to use for the link (get by default) * * @throws \InvalidArgumentException if the node is not a link * * @api */ public function __construct(\DOMNode $node, $currentUri, $method = 'GET') { if (!in_array(strtolower(substr($currentUri, 0, 4)), array('http', 'file'))) { throw new \InvalidArgumentException(sprintf('Current URI must be an absolute URL ("%s").', $currentUri)); } $this->setNode($node); $this->method = $method ? strtoupper($method) : null; $this->currentUri = $currentUri; } /** * Gets the node associated with this link. * * @return \DOMNode A \DOMNode instance */ public function getNode() { return $this->node; } /** * Gets the method associated with this link. * * @return string The method * * @api */ public function getMethod() { return $this->method; } /** * Gets the URI associated with this link. * * @return string The URI * * @api */ public function getUri() { $uri = trim($this->getRawUri()); // absolute URL? if (null !== parse_url($uri, PHP_URL_SCHEME)) { return $uri; } // empty URI if (!$uri) { return $this->currentUri; } // only an anchor if ('#' === $uri[0]) { $baseUri = $this->currentUri; if (false !== $pos = strpos($baseUri, '#')) { $baseUri = substr($baseUri, 0, $pos); } return $baseUri.$uri; } // only a query string if ('?' === $uri[0]) { $baseUri = $this->currentUri; // remove the query string from the current URI if (false !== $pos = strpos($baseUri, '?')) { $baseUri = substr($baseUri, 0, $pos); } return $baseUri.$uri; } // absolute URL with relative schema if (0 === strpos($uri, '//')) { return preg_replace('#^([^/]*)//.*$#', '$1', $this->currentUri).$uri; } $baseUri = preg_replace('#^(.*?//[^/]*)(?:\/.*)?$#', '$1', $this->currentUri); // absolute path if ('/' === $uri[0]) { return $baseUri.$uri; } // relative path $path = parse_url(substr($this->currentUri, strlen($baseUri)), PHP_URL_PATH); $path = $this->canonicalizePath(substr($path, 0, strrpos($path, '/')).'/'.$uri); return $baseUri.('' === $path || '/' !== $path[0] ? '/' : '').$path; } /** * Returns raw URI data. * * @return string */ protected function getRawUri() { return $this->node->getAttribute('href'); } /** * Returns the canonicalized URI path (see RFC 3986, section 5.2.4) * * @param string $path URI path * * @return string */ protected function canonicalizePath($path) { if ('' === $path || '/' === $path) { return $path; } if ('.' === substr($path, -1)) { $path = $path.'/'; } $output = array(); foreach (explode('/', $path) as $segment) { if ('..' === $segment) { array_pop($output); } elseif ('.' !== $segment) { array_push($output, $segment); } } return implode('/', $output); } /** * Sets current \DOMNode instance. * * @param \DOMNode $node A \DOMNode instance * * @throws \LogicException If given node is not an anchor */ protected function setNode(\DOMNode $node) { if ('a' != $node->nodeName && 'area' != $node->nodeName) { throw new \LogicException(sprintf('Unable to click on a "%s" tag.', $node->nodeName)); } $this->node = $node; } } PK]<4{bbDomCrawler/Crawler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler; use Symfony\Component\CssSelector\CssSelector; /** * Crawler eases navigation of a list of \DOMNode objects. * * @author Fabien Potencier * * @api */ class Crawler extends \SplObjectStorage { /** * @var string The current URI or the base href value */ protected $uri; /** * @var string The default namespace prefix to be used with XPath and CSS expressions */ private $defaultNamespacePrefix = 'default'; /** * @var array A map of manually registered namespaces */ private $namespaces = array(); /** * Constructor. * * @param mixed $node A Node to use as the base for the crawling * @param string $uri The current URI or the base href value * * @api */ public function __construct($node = null, $uri = null) { $this->uri = $uri; $this->add($node); } /** * Removes all the nodes. * * @api */ public function clear() { $this->removeAll($this); } /** * Adds a node to the current list of nodes. * * This method uses the appropriate specialized add*() method based * on the type of the argument. * * @param \DOMNodeList|\DOMNode|array|string|null $node A node * * @throws \InvalidArgumentException When node is not the expected type. * * @api */ public function add($node) { if ($node instanceof \DOMNodeList) { $this->addNodeList($node); } elseif ($node instanceof \DOMNode) { $this->addNode($node); } elseif (is_array($node)) { $this->addNodes($node); } elseif (is_string($node)) { $this->addContent($node); } elseif (null !== $node) { throw new \InvalidArgumentException(sprintf('Expecting a DOMNodeList or DOMNode instance, an array, a string, or null, but got "%s".', is_object($node) ? get_class($node) : gettype($node))); } } /** * Adds HTML/XML content. * * If the charset is not set via the content type, it is assumed * to be ISO-8859-1, which is the default charset defined by the * HTTP 1.1 specification. * * @param string $content A string to parse as HTML/XML * @param null|string $type The content type of the string */ public function addContent($content, $type = null) { if (empty($type)) { $type = 0 === strpos($content, ']+charset *= *["\']?([a-zA-Z\-0-9]+)/i', $content, $matches)) { $charset = $matches[1]; } if (null === $charset) { $charset = 'ISO-8859-1'; } if ('x' === $xmlMatches[1]) { $this->addXmlContent($content, $charset); } else { $this->addHtmlContent($content, $charset); } } /** * Adds an HTML content to the list of nodes. * * The libxml errors are disabled when the content is parsed. * * If you want to get parsing errors, be sure to enable * internal errors via libxml_use_internal_errors(true) * and then, get the errors via libxml_get_errors(). Be * sure to clear errors with libxml_clear_errors() afterward. * * @param string $content The HTML content * @param string $charset The charset * * @api */ public function addHtmlContent($content, $charset = 'UTF-8') { $internalErrors = libxml_use_internal_errors(true); $disableEntities = libxml_disable_entity_loader(true); $dom = new \DOMDocument('1.0', $charset); $dom->validateOnParse = true; if (function_exists('mb_convert_encoding')) { $hasError = false; set_error_handler(function () use (&$hasError) { $hasError = true; }); $tmpContent = @mb_convert_encoding($content, 'HTML-ENTITIES', $charset); restore_error_handler(); if (!$hasError) { $content = $tmpContent; } } if ('' !== trim($content)) { @$dom->loadHTML($content); } libxml_use_internal_errors($internalErrors); libxml_disable_entity_loader($disableEntities); $this->addDocument($dom); $base = $this->filterXPath('descendant-or-self::base')->extract(array('href')); $baseHref = current($base); if (count($base) && !empty($baseHref)) { if ($this->uri) { $linkNode = $dom->createElement('a'); $linkNode->setAttribute('href', $baseHref); $link = new Link($linkNode, $this->uri); $this->uri = $link->getUri(); } else { $this->uri = $baseHref; } } } /** * Adds an XML content to the list of nodes. * * The libxml errors are disabled when the content is parsed. * * If you want to get parsing errors, be sure to enable * internal errors via libxml_use_internal_errors(true) * and then, get the errors via libxml_get_errors(). Be * sure to clear errors with libxml_clear_errors() afterward. * * @param string $content The XML content * @param string $charset The charset * * @api */ public function addXmlContent($content, $charset = 'UTF-8') { // remove the default namespace if it's the only namespace to make XPath expressions simpler if (!preg_match('/xmlns:/', $content)) { $content = str_replace('xmlns', 'ns', $content); } $internalErrors = libxml_use_internal_errors(true); $disableEntities = libxml_disable_entity_loader(true); $dom = new \DOMDocument('1.0', $charset); $dom->validateOnParse = true; if ('' !== trim($content)) { @$dom->loadXML($content, LIBXML_NONET); } libxml_use_internal_errors($internalErrors); libxml_disable_entity_loader($disableEntities); $this->addDocument($dom); } /** * Adds a \DOMDocument to the list of nodes. * * @param \DOMDocument $dom A \DOMDocument instance * * @api */ public function addDocument(\DOMDocument $dom) { if ($dom->documentElement) { $this->addNode($dom->documentElement); } } /** * Adds a \DOMNodeList to the list of nodes. * * @param \DOMNodeList $nodes A \DOMNodeList instance * * @api */ public function addNodeList(\DOMNodeList $nodes) { foreach ($nodes as $node) { $this->addNode($node); } } /** * Adds an array of \DOMNode instances to the list of nodes. * * @param \DOMNode[] $nodes An array of \DOMNode instances * * @api */ public function addNodes(array $nodes) { foreach ($nodes as $node) { $this->add($node); } } /** * Adds a \DOMNode instance to the list of nodes. * * @param \DOMNode $node A \DOMNode instance * * @api */ public function addNode(\DOMNode $node) { if ($node instanceof \DOMDocument) { $this->attach($node->documentElement); } else { $this->attach($node); } } /** * Returns a node given its position in the node list. * * @param integer $position The position * * @return Crawler A new instance of the Crawler with the selected node, or an empty Crawler if it does not exist. * * @api */ public function eq($position) { foreach ($this as $i => $node) { if ($i == $position) { return new static($node, $this->uri); } } return new static(null, $this->uri); } /** * Calls an anonymous function on each node of the list. * * The anonymous function receives the position and the node wrapped * in a Crawler instance as arguments. * * Example: * * $crawler->filter('h1')->each(function ($node, $i) { * return $node->text(); * }); * * @param \Closure $closure An anonymous function * * @return array An array of values returned by the anonymous function * * @api */ public function each(\Closure $closure) { $data = array(); foreach ($this as $i => $node) { $data[] = $closure(new static($node, $this->uri), $i); } return $data; } /** * Reduces the list of nodes by calling an anonymous function. * * To remove a node from the list, the anonymous function must return false. * * @param \Closure $closure An anonymous function * * @return Crawler A Crawler instance with the selected nodes. * * @api */ public function reduce(\Closure $closure) { $nodes = array(); foreach ($this as $i => $node) { if (false !== $closure(new static($node, $this->uri), $i)) { $nodes[] = $node; } } return new static($nodes, $this->uri); } /** * Returns the first node of the current selection * * @return Crawler A Crawler instance with the first selected node * * @api */ public function first() { return $this->eq(0); } /** * Returns the last node of the current selection * * @return Crawler A Crawler instance with the last selected node * * @api */ public function last() { return $this->eq(count($this) - 1); } /** * Returns the siblings nodes of the current selection * * @return Crawler A Crawler instance with the sibling nodes * * @throws \InvalidArgumentException When current node is empty * * @api */ public function siblings() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } return new static($this->sibling($this->getNode(0)->parentNode->firstChild), $this->uri); } /** * Returns the next siblings nodes of the current selection * * @return Crawler A Crawler instance with the next sibling nodes * * @throws \InvalidArgumentException When current node is empty * * @api */ public function nextAll() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } return new static($this->sibling($this->getNode(0)), $this->uri); } /** * Returns the previous sibling nodes of the current selection * * @return Crawler A Crawler instance with the previous sibling nodes * * @throws \InvalidArgumentException * * @api */ public function previousAll() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } return new static($this->sibling($this->getNode(0), 'previousSibling'), $this->uri); } /** * Returns the parents nodes of the current selection * * @return Crawler A Crawler instance with the parents nodes of the current selection * * @throws \InvalidArgumentException When current node is empty * * @api */ public function parents() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $node = $this->getNode(0); $nodes = array(); while ($node = $node->parentNode) { if (1 === $node->nodeType && '_root' !== $node->nodeName) { $nodes[] = $node; } } return new static($nodes, $this->uri); } /** * Returns the children nodes of the current selection * * @return Crawler A Crawler instance with the children nodes * * @throws \InvalidArgumentException When current node is empty * * @api */ public function children() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $node = $this->getNode(0)->firstChild; return new static($node ? $this->sibling($node) : array(), $this->uri); } /** * Returns the attribute value of the first node of the list. * * @param string $attribute The attribute name * * @return string|null The attribute value or null if the attribute does not exist * * @throws \InvalidArgumentException When current node is empty * * @api */ public function attr($attribute) { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $node = $this->getNode(0); return $node->hasAttribute($attribute) ? $node->getAttribute($attribute) : null; } /** * Returns the node value of the first node of the list. * * @return string The node value * * @throws \InvalidArgumentException When current node is empty * * @api */ public function text() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } return $this->getNode(0)->nodeValue; } /** * Returns the first node of the list as HTML. * * @return string The node html * * @throws \InvalidArgumentException When current node is empty */ public function html() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $html = ''; foreach ($this->getNode(0)->childNodes as $child) { if (version_compare(PHP_VERSION, '5.3.6', '>=')) { // node parameter was added to the saveHTML() method in PHP 5.3.6 // @see http://php.net/manual/en/domdocument.savehtml.php $html .= $child->ownerDocument->saveHTML($child); } else { $document = new \DOMDocument('1.0', 'UTF-8'); $document->appendChild($document->importNode($child, true)); $html .= rtrim($document->saveHTML()); } } return $html; } /** * Extracts information from the list of nodes. * * You can extract attributes or/and the node value (_text). * * Example: * * $crawler->filter('h1 a')->extract(array('_text', 'href')); * * @param array $attributes An array of attributes * * @return array An array of extracted values * * @api */ public function extract($attributes) { $attributes = (array) $attributes; $count = count($attributes); $data = array(); foreach ($this as $node) { $elements = array(); foreach ($attributes as $attribute) { if ('_text' === $attribute) { $elements[] = $node->nodeValue; } else { $elements[] = $node->getAttribute($attribute); } } $data[] = $count > 1 ? $elements : $elements[0]; } return $data; } /** * Filters the list of nodes with an XPath expression. * * @param string $xpath An XPath expression * * @return Crawler A new instance of Crawler with the filtered list of nodes * * @api */ public function filterXPath($xpath) { $document = new \DOMDocument('1.0', 'UTF-8'); $root = $document->appendChild($document->createElement('_root')); foreach ($this as $node) { $root->appendChild($document->importNode($node, true)); } $prefixes = $this->findNamespacePrefixes($xpath); $domxpath = $this->createDOMXPath($document, $prefixes); return new static($domxpath->query($xpath), $this->uri); } /** * Filters the list of nodes with a CSS selector. * * This method only works if you have installed the CssSelector Symfony Component. * * @param string $selector A CSS selector * * @return Crawler A new instance of Crawler with the filtered list of nodes * * @throws \RuntimeException if the CssSelector Component is not available * * @api */ public function filter($selector) { if (!class_exists('Symfony\\Component\\CssSelector\\CssSelector')) { // @codeCoverageIgnoreStart throw new \RuntimeException('Unable to filter with a CSS selector as the Symfony CssSelector is not installed (you can use filterXPath instead).'); // @codeCoverageIgnoreEnd } return $this->filterXPath(CssSelector::toXPath($selector)); } /** * Selects links by name or alt value for clickable images. * * @param string $value The link text * * @return Crawler A new instance of Crawler with the filtered list of nodes * * @api */ public function selectLink($value) { $xpath = sprintf('//a[contains(concat(\' \', normalize-space(string(.)), \' \'), %s)] ', static::xpathLiteral(' '.$value.' ')). sprintf('| //a/img[contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)]/ancestor::a', static::xpathLiteral(' '.$value.' ')); return $this->filterXPath($xpath); } /** * Selects a button by name or alt value for images. * * @param string $value The button text * * @return Crawler A new instance of Crawler with the filtered list of nodes * * @api */ public function selectButton($value) { $xpath = sprintf('//input[((@type="submit" or @type="button") and contains(concat(\' \', normalize-space(string(@value)), \' \'), %s)) ', static::xpathLiteral(' '.$value.' ')). sprintf('or (@type="image" and contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)) or @id="%s" or @name="%s"] ', static::xpathLiteral(' '.$value.' '), $value, $value). sprintf('| //button[contains(concat(\' \', normalize-space(string(.)), \' \'), %s) or @id="%s" or @name="%s"]', static::xpathLiteral(' '.$value.' '), $value, $value); return $this->filterXPath($xpath); } /** * Returns a Link object for the first node in the list. * * @param string $method The method for the link (get by default) * * @return Link A Link instance * * @throws \InvalidArgumentException If the current node list is empty * * @api */ public function link($method = 'get') { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $node = $this->getNode(0); return new Link($node, $this->uri, $method); } /** * Returns an array of Link objects for the nodes in the list. * * @return Link[] An array of Link instances * * @api */ public function links() { $links = array(); foreach ($this as $node) { $links[] = new Link($node, $this->uri, 'get'); } return $links; } /** * Returns a Form object for the first node in the list. * * @param array $values An array of values for the form fields * @param string $method The method for the form * * @return Form A Form instance * * @throws \InvalidArgumentException If the current node list is empty * * @api */ public function form(array $values = null, $method = null) { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $form = new Form($this->getNode(0), $this->uri, $method); if (null !== $values) { $form->setValues($values); } return $form; } /** * Overloads a default namespace prefix to be used with XPath and CSS expressions. * * @param string $prefix */ public function setDefaultNamespacePrefix($prefix) { $this->defaultNamespacePrefix = $prefix; } /** * @param string $prefix * @param string $namespace */ public function registerNamespace($prefix, $namespace) { $this->namespaces[$prefix] = $namespace; } /** * Converts string for XPath expressions. * * Escaped characters are: quotes (") and apostrophe ('). * * Examples: * * echo Crawler::xpathLiteral('foo " bar'); * //prints 'foo " bar' * * echo Crawler::xpathLiteral("foo ' bar"); * //prints "foo ' bar" * * echo Crawler::xpathLiteral('a\'b"c'); * //prints concat('a', "'", 'b"c') * * * @param string $s String to be escaped * * @return string Converted string */ public static function xpathLiteral($s) { if (false === strpos($s, "'")) { return sprintf("'%s'", $s); } if (false === strpos($s, '"')) { return sprintf('"%s"', $s); } $string = $s; $parts = array(); while (true) { if (false !== $pos = strpos($string, "'")) { $parts[] = sprintf("'%s'", substr($string, 0, $pos)); $parts[] = "\"'\""; $string = substr($string, $pos + 1); } else { $parts[] = "'$string'"; break; } } return sprintf("concat(%s)", implode($parts, ', ')); } /** * @param integer $position * * @return \DOMElement|null */ public function getNode($position) { foreach ($this as $i => $node) { if ($i == $position) { return $node; } // @codeCoverageIgnoreStart } return null; // @codeCoverageIgnoreEnd } /** * @param \DOMElement $node * @param string $siblingDir * * @return array */ protected function sibling($node, $siblingDir = 'nextSibling') { $nodes = array(); do { if ($node !== $this->getNode(0) && $node->nodeType === 1) { $nodes[] = $node; } } while ($node = $node->$siblingDir); return $nodes; } /** * @param \DOMDocument $document * @param array $prefixes * * @return \DOMXPath * * @throws \InvalidArgumentException */ private function createDOMXPath(\DOMDocument $document, array $prefixes = array()) { $domxpath = new \DOMXPath($document); foreach ($prefixes as $prefix) { $namespace = $this->discoverNamespace($domxpath, $prefix); if (null !== $namespace) { $domxpath->registerNamespace($prefix, $namespace); } } return $domxpath; } /** * @param \DOMXPath $domxpath * @param string $prefix * * @return string * * @throws \InvalidArgumentException */ private function discoverNamespace(\DOMXPath $domxpath, $prefix) { if (isset($this->namespaces[$prefix])) { return $this->namespaces[$prefix]; } // ask for one namespace, otherwise we'd get a collection with an item for each node $namespaces = $domxpath->query(sprintf('(//namespace::*[name()="%s"])[last()]', $this->defaultNamespacePrefix === $prefix ? '' : $prefix)); if ($node = $namespaces->item(0)) { return $node->nodeValue; } } /** * @param $xpath * * @return array */ private function findNamespacePrefixes($xpath) { if (preg_match_all('/(?P[a-z_][a-z_0-9\-\.]*):[^"\/]/i', $xpath, $matches)) { return array_unique($matches['prefix']); } return array(); } } PK]V * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler; use Symfony\Component\DomCrawler\Field\FormField; /** * This is an internal class that must not be used directly. */ class FormFieldRegistry { private $fields = array(); private $base; /** * Adds a field to the registry. * * @param FormField $field The field * * @throws \InvalidArgumentException when the name is malformed */ public function add(FormField $field) { $segments = $this->getSegments($field->getName()); $target =& $this->fields; while ($segments) { if (!is_array($target)) { $target = array(); } $path = array_shift($segments); if ('' === $path) { $target =& $target[]; } else { $target =& $target[$path]; } } $target = $field; } /** * Removes a field and its children from the registry. * * @param string $name The fully qualified name of the base field * * @throws \InvalidArgumentException when the name is malformed */ public function remove($name) { $segments = $this->getSegments($name); $target =& $this->fields; while (count($segments) > 1) { $path = array_shift($segments); if (!array_key_exists($path, $target)) { return; } $target =& $target[$path]; } unset($target[array_shift($segments)]); } /** * Returns the value of the field and its children. * * @param string $name The fully qualified name of the field * * @return mixed The value of the field * * @throws \InvalidArgumentException when the name is malformed * @throws \InvalidArgumentException if the field does not exist */ public function &get($name) { $segments = $this->getSegments($name); $target =& $this->fields; while ($segments) { $path = array_shift($segments); if (!array_key_exists($path, $target)) { throw new \InvalidArgumentException(sprintf('Unreachable field "%s"', $path)); } $target =& $target[$path]; } return $target; } /** * Tests whether the form has the given field. * * @param string $name The fully qualified name of the field * * @return Boolean Whether the form has the given field */ public function has($name) { try { $this->get($name); return true; } catch (\InvalidArgumentException $e) { return false; } } /** * Set the value of a field and its children. * * @param string $name The fully qualified name of the field * @param mixed $value The value * * @throws \InvalidArgumentException when the name is malformed * @throws \InvalidArgumentException if the field does not exist */ public function set($name, $value) { $target =& $this->get($name); if (!is_array($value) || $target instanceof Field\ChoiceFormField) { $target->setValue($value); } else { $fields = self::create($name, $value); foreach ($fields->all() as $k => $v) { $this->set($k, $v); } } } /** * Returns the list of field with their value. * * @return array The list of fields as array((string) Fully qualified name => (mixed) value) */ public function all() { return $this->walk($this->fields, $this->base); } /** * Creates an instance of the class. * * This function is made private because it allows overriding the $base and * the $values properties without any type checking. * * @param string $base The fully qualified name of the base field * @param array $values The values of the fields * * @return FormFieldRegistry */ private static function create($base, array $values) { $registry = new static(); $registry->base = $base; $registry->fields = $values; return $registry; } /** * Transforms a PHP array in a list of fully qualified name / value. * * @param array $array The PHP array * @param string $base The name of the base field * @param array $output The initial values * * @return array The list of fields as array((string) Fully qualified name => (mixed) value) */ private function walk(array $array, $base = '', array &$output = array()) { foreach ($array as $k => $v) { $path = empty($base) ? $k : sprintf("%s[%s]", $base, $k); if (is_array($v)) { $this->walk($v, $path, $output); } else { $output[$path] = $v; } } return $output; } /** * Splits a field name into segments as a web browser would do. * * * getSegments('base[foo][3][]') = array('base', 'foo, '3', ''); * * * @param string $name The name of the field * * @return array The list of segments * * @throws \InvalidArgumentException when the name is malformed */ private function getSegments($name) { if (preg_match('/^(?P[^[]+)(?P(\[.*)|$)/', $name, $m)) { $segments = array($m['base']); while (!empty($m['extra'])) { if (preg_match('/^\[(?P.*?)\](?P.*)$/', $m['extra'], $m)) { $segments[] = $m['segment']; } else { throw new \InvalidArgumentException(sprintf('Malformed field path "%s"', $name)); } } return $segments; } throw new \InvalidArgumentException(sprintf('Malformed field path "%s"', $name)); } } PK] ʀ&DomCrawler/Field/TextareaFormField.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler\Field; /** * TextareaFormField represents a textarea form field (an HTML textarea tag). * * @author Fabien Potencier * * @api */ class TextareaFormField extends FormField { /** * Initializes the form field. * * @throws \LogicException When node type is incorrect */ protected function initialize() { if ('textarea' != $this->node->nodeName) { throw new \LogicException(sprintf('A TextareaFormField can only be created from a textarea tag (%s given).', $this->node->nodeName)); } $this->value = null; foreach ($this->node->childNodes as $node) { $this->value .= $node->wholeText; } } } PK]#DomCrawler/Field/InputFormField.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler\Field; /** * InputFormField represents an input form field (an HTML input tag). * * For inputs with type of file, checkbox, or radio, there are other more * specialized classes (cf. FileFormField and ChoiceFormField). * * @author Fabien Potencier * * @api */ class InputFormField extends FormField { /** * Initializes the form field. * * @throws \LogicException When node type is incorrect */ protected function initialize() { if ('input' != $this->node->nodeName && 'button' != $this->node->nodeName) { throw new \LogicException(sprintf('An InputFormField can only be created from an input or button tag (%s given).', $this->node->nodeName)); } if ('checkbox' == $this->node->getAttribute('type')) { throw new \LogicException('Checkboxes should be instances of ChoiceFormField.'); } if ('file' == $this->node->getAttribute('type')) { throw new \LogicException('File inputs should be instances of FileFormField.'); } $this->value = $this->node->getAttribute('value'); } } PK]bڋvB B "DomCrawler/Field/FileFormField.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler\Field; /** * FileFormField represents a file form field (an HTML file input tag). * * @author Fabien Potencier * * @api */ class FileFormField extends FormField { /** * Sets the PHP error code associated with the field. * * @param integer $error The error code (one of UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, or UPLOAD_ERR_EXTENSION) * * @throws \InvalidArgumentException When error code doesn't exist */ public function setErrorCode($error) { $codes = array(UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, UPLOAD_ERR_EXTENSION); if (!in_array($error, $codes)) { throw new \InvalidArgumentException(sprintf('The error code %s is not valid.', $error)); } $this->value = array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => $error, 'size' => 0); } /** * Sets the value of the field. * * @param string $value The value of the field * * @api */ public function upload($value) { $this->setValue($value); } /** * Sets the value of the field. * * @param string $value The value of the field */ public function setValue($value) { if (null !== $value && is_readable($value)) { $error = UPLOAD_ERR_OK; $size = filesize($value); $info = pathinfo($value); $name = $info['basename']; // copy to a tmp location $tmp = sys_get_temp_dir().'/'.sha1(uniqid(mt_rand(), true)); if (array_key_exists('extension', $info)) { $tmp .= '.'.$info['extension']; } if (is_file($tmp)) { unlink($tmp); } copy($value, $tmp); $value = $tmp; } else { $error = UPLOAD_ERR_NO_FILE; $size = 0; $name = ''; $value = ''; } $this->value = array('name' => $name, 'type' => '', 'tmp_name' => $value, 'error' => $error, 'size' => $size); } /** * Sets path to the file as string for simulating HTTP request * * @param string $path The path to the file */ public function setFilePath($path) { parent::setValue($path); } /** * Initializes the form field. * * @throws \LogicException When node type is incorrect */ protected function initialize() { if ('input' != $this->node->nodeName) { throw new \LogicException(sprintf('A FileFormField can only be created from an input tag (%s given).', $this->node->nodeName)); } if ('file' != $this->node->getAttribute('type')) { throw new \LogicException(sprintf('A FileFormField can only be created from an input tag with a type of file (given type is %s).', $this->node->getAttribute('type'))); } $this->setValue(null); } } PK] Y[$[$$DomCrawler/Field/ChoiceFormField.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler\Field; /** * ChoiceFormField represents a choice form field. * * It is constructed from a HTML select tag, or a HTML checkbox, or radio inputs. * * @author Fabien Potencier * * @api */ class ChoiceFormField extends FormField { /** * @var string */ private $type; /** * @var Boolean */ private $multiple; /** * @var array */ private $options; /** * @var boolean */ private $validationDisabled = false; /** * Returns true if the field should be included in the submitted values. * * @return Boolean true if the field should be included in the submitted values, false otherwise */ public function hasValue() { // don't send a value for unchecked checkboxes if (in_array($this->type, array('checkbox', 'radio')) && null === $this->value) { return false; } return true; } /** * Check if the current selected option is disabled * * @return Boolean */ public function isDisabled() { foreach ($this->options as $option) { if ($option['value'] == $this->value && $option['disabled']) { return true; } } return false; } /** * Sets the value of the field. * * @param string $value The value of the field * * @api */ public function select($value) { $this->setValue($value); } /** * Ticks a checkbox. * * @throws \LogicException When the type provided is not correct * * @api */ public function tick() { if ('checkbox' !== $this->type) { throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type)); } $this->setValue(true); } /** * Ticks a checkbox. * * @throws \LogicException When the type provided is not correct * * @api */ public function untick() { if ('checkbox' !== $this->type) { throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type)); } $this->setValue(false); } /** * Sets the value of the field. * * @param string $value The value of the field * * @throws \InvalidArgumentException When value type provided is not correct */ public function setValue($value) { if ('checkbox' == $this->type && false === $value) { // uncheck $this->value = null; } elseif ('checkbox' == $this->type && true === $value) { // check $this->value = $this->options[0]['value']; } else { if (is_array($value)) { if (!$this->multiple) { throw new \InvalidArgumentException(sprintf('The value for "%s" cannot be an array.', $this->name)); } foreach ($value as $v) { if (!$this->containsOption($v, $this->options)) { throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $v, implode(', ', $this->availableOptionValues()))); } } } elseif (!$this->containsOption($value, $this->options)) { throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $value, implode(', ', $this->availableOptionValues()))); } if ($this->multiple) { $value = (array) $value; } if (is_array($value)) { $this->value = $value; } else { parent::setValue($value); } } } /** * Adds a choice to the current ones. * * This method should only be used internally. * * @param \DOMNode $node A \DOMNode * * @throws \LogicException When choice provided is not multiple nor radio */ public function addChoice(\DOMNode $node) { if (!$this->multiple && 'radio' != $this->type) { throw new \LogicException(sprintf('Unable to add a choice for "%s" as it is not multiple or is not a radio button.', $this->name)); } $option = $this->buildOptionValue($node); $this->options[] = $option; if ($node->getAttribute('checked')) { $this->value = $option['value']; } } /** * Returns the type of the choice field (radio, select, or checkbox). * * @return string The type */ public function getType() { return $this->type; } /** * Returns true if the field accepts multiple values. * * @return Boolean true if the field accepts multiple values, false otherwise */ public function isMultiple() { return $this->multiple; } /** * Initializes the form field. * * @throws \LogicException When node type is incorrect */ protected function initialize() { if ('input' != $this->node->nodeName && 'select' != $this->node->nodeName) { throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input or select tag (%s given).', $this->node->nodeName)); } if ('input' == $this->node->nodeName && 'checkbox' != $this->node->getAttribute('type') && 'radio' != $this->node->getAttribute('type')) { throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input tag with a type of checkbox or radio (given type is %s).', $this->node->getAttribute('type'))); } $this->value = null; $this->options = array(); $this->multiple = false; if ('input' == $this->node->nodeName) { $this->type = $this->node->getAttribute('type'); $optionValue = $this->buildOptionValue($this->node); $this->options[] = $optionValue; if ($this->node->getAttribute('checked')) { $this->value = $optionValue['value']; } } else { $this->type = 'select'; if ($this->node->hasAttribute('multiple')) { $this->multiple = true; $this->value = array(); $this->name = str_replace('[]', '', $this->name); } $found = false; foreach ($this->xpath->query('descendant::option', $this->node) as $option) { $this->options[] = $this->buildOptionValue($option); if ($option->getAttribute('selected')) { $found = true; if ($this->multiple) { $this->value[] = $option->getAttribute('value'); } else { $this->value = $option->getAttribute('value'); } } } // if no option is selected and if it is a simple select box, take the first option as the value $option = $this->xpath->query('descendant::option', $this->node)->item(0); if (!$found && !$this->multiple && $option instanceof \DOMElement) { $this->value = $option->getAttribute('value'); } } } /** * Returns option value with associated disabled flag * * @param \DOMNode $node * * @return array */ private function buildOptionValue($node) { $option = array(); $defaultValue = (isset($node->nodeValue) && !empty($node->nodeValue)) ? $node->nodeValue : '1'; $option['value'] = $node->hasAttribute('value') ? $node->getAttribute('value') : $defaultValue; $option['disabled'] = ($node->hasAttribute('disabled') && $node->getAttribute('disabled') == 'disabled'); return $option; } /** * Checks whether given vale is in the existing options * * @param string $optionValue * @param array $options * * @return bool */ public function containsOption($optionValue, $options) { if ($this->validationDisabled) { return true; } foreach ($options as $option) { if ($option['value'] == $optionValue) { return true; } } return false; } /** * Returns list of available field options * * @return array */ public function availableOptionValues() { $values = array(); foreach ($this->options as $option) { $values[] = $option['value']; } return $values; } /** * Disables the internal validation of the field. * * @return self */ public function disableValidation() { $this->validationDisabled = true; return $this; } } PK]\Ud DomCrawler/Field/FormField.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler\Field; /** * FormField is the abstract class for all form fields. * * @author Fabien Potencier */ abstract class FormField { /** * @var \DOMNode */ protected $node; /** * @var string */ protected $name; /** * @var string */ protected $value; /** * @var \DOMDocument */ protected $document; /** * @var \DOMXPath */ protected $xpath; /** * @var Boolean */ protected $disabled; /** * Constructor. * * @param \DOMNode $node The node associated with this field */ public function __construct(\DOMNode $node) { $this->node = $node; $this->name = $node->getAttribute('name'); $this->document = new \DOMDocument('1.0', 'UTF-8'); $this->node = $this->document->importNode($this->node, true); $root = $this->document->appendChild($this->document->createElement('_root')); $root->appendChild($this->node); $this->xpath = new \DOMXPath($this->document); $this->initialize(); } /** * Returns the name of the field. * * @return string The name of the field */ public function getName() { return $this->name; } /** * Gets the value of the field. * * @return string|array The value of the field */ public function getValue() { return $this->value; } /** * Sets the value of the field. * * @param string $value The value of the field * * @api */ public function setValue($value) { $this->value = (string) $value; } /** * Returns true if the field should be included in the submitted values. * * @return Boolean true if the field should be included in the submitted values, false otherwise */ public function hasValue() { return true; } /** * Check if the current field is disabled * * @return Boolean */ public function isDisabled() { return $this->node->hasAttribute('disabled'); } /** * Initializes the form field. */ abstract protected function initialize(); } PK] H7H7DomCrawler/Form.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler; use Symfony\Component\DomCrawler\Field\FormField; /** * Form represents an HTML form. * * @author Fabien Potencier * * @api */ class Form extends Link implements \ArrayAccess { /** * @var \DOMNode */ private $button; /** * @var Field\FormField[] */ private $fields; /** * Constructor. * * @param \DOMNode $node A \DOMNode instance * @param string $currentUri The URI of the page where the form is embedded * @param string $method The method to use for the link (if null, it defaults to the method defined by the form) * * @throws \LogicException if the node is not a button inside a form tag * * @api */ public function __construct(\DOMNode $node, $currentUri, $method = null) { parent::__construct($node, $currentUri, $method); $this->initialize(); } /** * Gets the form node associated with this form. * * @return \DOMNode A \DOMNode instance */ public function getFormNode() { return $this->node; } /** * Sets the value of the fields. * * @param array $values An array of field values * * @return Form * * @api */ public function setValues(array $values) { foreach ($values as $name => $value) { $this->fields->set($name, $value); } return $this; } /** * Gets the field values. * * The returned array does not include file fields (@see getFiles). * * @return array An array of field values. * * @api */ public function getValues() { $values = array(); foreach ($this->fields->all() as $name => $field) { if ($field->isDisabled()) { continue; } if (!$field instanceof Field\FileFormField && $field->hasValue()) { $values[$name] = $field->getValue(); } } return $values; } /** * Gets the file field values. * * @return array An array of file field values. * * @api */ public function getFiles() { if (!in_array($this->getMethod(), array('POST', 'PUT', 'DELETE', 'PATCH'))) { return array(); } $files = array(); foreach ($this->fields->all() as $name => $field) { if ($field->isDisabled()) { continue; } if ($field instanceof Field\FileFormField) { $files[$name] = $field->getValue(); } } return $files; } /** * Gets the field values as PHP. * * This method converts fields with the array notation * (like foo[bar] to arrays) like PHP does. * * @return array An array of field values. * * @api */ public function getPhpValues() { $values = array(); foreach ($this->getValues() as $name => $value) { $qs = http_build_query(array($name => $value), '', '&'); parse_str($qs, $expandedValue); $varName = substr($name, 0, strlen(key($expandedValue))); $values = array_replace_recursive($values, array($varName => current($expandedValue))); } return $values; } /** * Gets the file field values as PHP. * * This method converts fields with the array notation * (like foo[bar] to arrays) like PHP does. * * @return array An array of field values. * * @api */ public function getPhpFiles() { $values = array(); foreach ($this->getFiles() as $name => $value) { $qs = http_build_query(array($name => $value), '', '&'); parse_str($qs, $expandedValue); $varName = substr($name, 0, strlen(key($expandedValue))); $values = array_replace_recursive($values, array($varName => current($expandedValue))); } return $values; } /** * Gets the URI of the form. * * The returned URI is not the same as the form "action" attribute. * This method merges the value if the method is GET to mimics * browser behavior. * * @return string The URI * * @api */ public function getUri() { $uri = parent::getUri(); if (!in_array($this->getMethod(), array('POST', 'PUT', 'DELETE', 'PATCH')) && $queryString = http_build_query($this->getValues(), null, '&')) { $sep = false === strpos($uri, '?') ? '?' : '&'; $uri .= $sep.$queryString; } return $uri; } protected function getRawUri() { return $this->node->getAttribute('action'); } /** * Gets the form method. * * If no method is defined in the form, GET is returned. * * @return string The method * * @api */ public function getMethod() { if (null !== $this->method) { return $this->method; } return $this->node->getAttribute('method') ? strtoupper($this->node->getAttribute('method')) : 'GET'; } /** * Returns true if the named field exists. * * @param string $name The field name * * @return Boolean true if the field exists, false otherwise * * @api */ public function has($name) { return $this->fields->has($name); } /** * Removes a field from the form. * * @param string $name The field name * * @throws \InvalidArgumentException when the name is malformed * * @api */ public function remove($name) { $this->fields->remove($name); } /** * Gets a named field. * * @param string $name The field name * * @return FormField The field instance * * @throws \InvalidArgumentException When field is not present in this form * * @api */ public function get($name) { return $this->fields->get($name); } /** * Sets a named field. * * @param FormField $field The field * * @api */ public function set(FormField $field) { $this->fields->add($field); } /** * Gets all fields. * * @return FormField[] An array of fields * * @api */ public function all() { return $this->fields->all(); } /** * Returns true if the named field exists. * * @param string $name The field name * * @return Boolean true if the field exists, false otherwise */ public function offsetExists($name) { return $this->has($name); } /** * Gets the value of a field. * * @param string $name The field name * * @return FormField The associated Field instance * * @throws \InvalidArgumentException if the field does not exist */ public function offsetGet($name) { return $this->fields->get($name); } /** * Sets the value of a field. * * @param string $name The field name * @param string|array $value The value of the field * * @throws \InvalidArgumentException if the field does not exist */ public function offsetSet($name, $value) { $this->fields->set($name, $value); } /** * Removes a field from the form. * * @param string $name The field name */ public function offsetUnset($name) { $this->fields->remove($name); } /** * Disables validation * * @return self */ public function disableValidation() { foreach ($this->fields->all() as $field) { if ($field instanceof Field\ChoiceFormField) { $field->disableValidation(); } } return $this; } /** * Sets the node for the form. * * Expects a 'submit' button \DOMNode and finds the corresponding form element. * * @param \DOMNode $node A \DOMNode instance * * @throws \LogicException If given node is not a button or input or does not have a form ancestor */ protected function setNode(\DOMNode $node) { $this->button = $node; if ('button' == $node->nodeName || ('input' == $node->nodeName && in_array($node->getAttribute('type'), array('submit', 'button', 'image')))) { if ($node->hasAttribute('form')) { // if the node has the HTML5-compliant 'form' attribute, use it $formId = $node->getAttribute('form'); $form = $node->ownerDocument->getElementById($formId); if (null === $form) { throw new \LogicException(sprintf('The selected node has an invalid form attribute (%s).', $formId)); } $this->node = $form; return; } // we loop until we find a form ancestor do { if (null === $node = $node->parentNode) { throw new \LogicException('The selected node does not have a form ancestor.'); } } while ('form' != $node->nodeName); } elseif ('form' != $node->nodeName) { throw new \LogicException(sprintf('Unable to submit on a "%s" tag.', $node->nodeName)); } $this->node = $node; } /** * Adds form elements related to this form. * * Creates an internal copy of the submitted 'button' element and * the form node or the entire document depending on whether we need * to find non-descendant elements through HTML5 'form' attribute. */ private function initialize() { $this->fields = new FormFieldRegistry(); $document = new \DOMDocument('1.0', 'UTF-8'); $xpath = new \DOMXPath($document); $root = $document->appendChild($document->createElement('_root')); // add submitted button if it has a valid name if ('form' !== $this->button->nodeName && $this->button->hasAttribute('name') && $this->button->getAttribute('name')) { if ('input' == $this->button->nodeName && 'image' == $this->button->getAttribute('type')) { $name = $this->button->getAttribute('name'); $this->button->setAttribute('value', '0'); // temporarily change the name of the input node for the x coordinate $this->button->setAttribute('name', $name.'.x'); $this->set(new Field\InputFormField($document->importNode($this->button, true))); // temporarily change the name of the input node for the y coordinate $this->button->setAttribute('name', $name.'.y'); $this->set(new Field\InputFormField($document->importNode($this->button, true))); // restore the original name of the input node $this->button->setAttribute('name', $name); } else { $this->set(new Field\InputFormField($document->importNode($this->button, true))); } } // find form elements corresponding to the current form if ($this->node->hasAttribute('id')) { // traverse through the whole document $node = $document->importNode($this->node->ownerDocument->documentElement, true); $root->appendChild($node); // corresponding elements are either descendants or have a matching HTML5 form attribute $formId = Crawler::xpathLiteral($this->node->getAttribute('id')); $fieldNodes = $xpath->query(sprintf('descendant::input[@form=%s] | descendant::button[@form=%s] | descendant::textarea[@form=%s] | descendant::select[@form=%s] | //form[@id=%s]//input[not(@form)] | //form[@id=%s]//button[not(@form)] | //form[@id=%s]//textarea[not(@form)] | //form[@id=%s]//select[not(@form)]', $formId, $formId, $formId, $formId, $formId, $formId, $formId, $formId), $root); foreach ($fieldNodes as $node) { $this->addField($node); } } else { // parent form has no id, add descendant elements only $node = $document->importNode($this->node, true); $root->appendChild($node); // descendant elements with form attribute are not part of this form $fieldNodes = $xpath->query('descendant::input[not(@form)] | descendant::button[not(@form)] | descendant::textarea[not(@form)] | descendant::select[not(@form)]', $root); foreach ($fieldNodes as $node) { $this->addField($node); } } } private function addField(\DOMNode $node) { if (!$node->hasAttribute('name') || !$node->getAttribute('name')) { return; } $nodeName = $node->nodeName; if ('select' == $nodeName || 'input' == $nodeName && 'checkbox' == $node->getAttribute('type')) { $this->set(new Field\ChoiceFormField($node)); } elseif ('input' == $nodeName && 'radio' == $node->getAttribute('type')) { if ($this->has($node->getAttribute('name'))) { $this->get($node->getAttribute('name'))->addChoice($node); } else { $this->set(new Field\ChoiceFormField($node)); } } elseif ('input' == $nodeName && 'file' == $node->getAttribute('type')) { $this->set(new Field\FileFormField($node)); } elseif ('input' == $nodeName && !in_array($node->getAttribute('type'), array('submit', 'button', 'image'))) { $this->set(new Field\InputFormField($node)); } elseif ('textarea' == $nodeName) { $this->set(new Field\TextareaFormField($node)); } } } PK]LoTTDomCrawler/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * CompiledRoutes are returned by the RouteCompiler class. * * @author Fabien Potencier */ class CompiledRoute { private $variables; private $tokens; private $staticPrefix; private $regex; private $pathVariables; private $hostVariables; private $hostRegex; private $hostTokens; /** * Constructor. * * @param string $staticPrefix The static prefix of the compiled route * @param string $regex The regular expression to use to match this route * @param array $tokens An array of tokens to use to generate URL for this route * @param array $pathVariables An array of path variables * @param string|null $hostRegex Host regex * @param array $hostTokens Host tokens * @param array $hostVariables An array of host variables * @param array $variables An array of variables (variables defined in the path and in the host patterns) */ public function __construct($staticPrefix, $regex, array $tokens, array $pathVariables, $hostRegex = null, array $hostTokens = array(), array $hostVariables = array(), array $variables = array()) { $this->staticPrefix = (string) $staticPrefix; $this->regex = $regex; $this->tokens = $tokens; $this->pathVariables = $pathVariables; $this->hostRegex = $hostRegex; $this->hostTokens = $hostTokens; $this->hostVariables = $hostVariables; $this->variables = $variables; } /** * Returns the static prefix. * * @return string The static prefix */ public function getStaticPrefix() { return $this->staticPrefix; } /** * Returns the regex. * * @return string The regex */ public function getRegex() { return $this->regex; } /** * Returns the host regex * * @return string|null The host regex or null */ public function getHostRegex() { return $this->hostRegex; } /** * Returns the tokens. * * @return array The tokens */ public function getTokens() { return $this->tokens; } /** * Returns the host tokens. * * @return array The tokens */ public function getHostTokens() { return $this->hostTokens; } /** * Returns the variables. * * @return array The variables */ public function getVariables() { return $this->variables; } /** * Returns the path variables. * * @return array The variables */ public function getPathVariables() { return $this->pathVariables; } /** * Returns the host variables. * * @return array The variables */ public function getHostVariables() { return $this->hostVariables; } } PK]''Routing/RouteCompiler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * RouteCompiler compiles Route instances to CompiledRoute instances. * * @author Fabien Potencier * @author Tobias Schultze */ class RouteCompiler implements RouteCompilerInterface { const REGEX_DELIMITER = '#'; /** * This string defines the characters that are automatically considered separators in front of * optional placeholders (with default and no static text following). Such a single separator * can be left out together with the optional placeholder from matching and generating URLs. */ const SEPARATORS = '/,;.:-_~+*=@|'; /** * {@inheritDoc} * * @throws \LogicException If a variable is referenced more than once * @throws \DomainException If a variable name is numeric because PHP raises an error for such * subpatterns in PCRE and thus would break matching, e.g. "(?P<123>.+)". */ public static function compile(Route $route) { $staticPrefix = null; $hostVariables = array(); $pathVariables = array(); $variables = array(); $tokens = array(); $regex = null; $hostRegex = null; $hostTokens = array(); if ('' !== $host = $route->getHost()) { $result = self::compilePattern($route, $host, true); $hostVariables = $result['variables']; $variables = array_merge($variables, $hostVariables); $hostTokens = $result['tokens']; $hostRegex = $result['regex']; } $path = $route->getPath(); $result = self::compilePattern($route, $path, false); $staticPrefix = $result['staticPrefix']; $pathVariables = $result['variables']; $variables = array_merge($variables, $pathVariables); $tokens = $result['tokens']; $regex = $result['regex']; return new CompiledRoute( $staticPrefix, $regex, $tokens, $pathVariables, $hostRegex, $hostTokens, $hostVariables, array_unique($variables) ); } private static function compilePattern(Route $route, $pattern, $isHost) { $tokens = array(); $variables = array(); $matches = array(); $pos = 0; $defaultSeparator = $isHost ? '.' : '/'; // Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable // in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself. preg_match_all('#\{\w+\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); foreach ($matches as $match) { $varName = substr($match[0][0], 1, -1); // get all static text preceding the current variable $precedingText = substr($pattern, $pos, $match[0][1] - $pos); $pos = $match[0][1] + strlen($match[0][0]); $precedingChar = strlen($precedingText) > 0 ? substr($precedingText, -1) : ''; $isSeparator = '' !== $precedingChar && false !== strpos(static::SEPARATORS, $precedingChar); if (is_numeric($varName)) { throw new \DomainException(sprintf('Variable name "%s" cannot be numeric in route pattern "%s". Please use a different name.', $varName, $pattern)); } if (in_array($varName, $variables)) { throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); } if ($isSeparator && strlen($precedingText) > 1) { $tokens[] = array('text', substr($precedingText, 0, -1)); } elseif (!$isSeparator && strlen($precedingText) > 0) { $tokens[] = array('text', $precedingText); } $regexp = $route->getRequirement($varName); if (null === $regexp) { $followingPattern = (string) substr($pattern, $pos); // Find the next static character after the variable that functions as a separator. By default, this separator and '/' // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are // the same that will be matched. Example: new Route('/{page}.{_format}', array('_format' => 'html')) // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything. // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally // part of {_format} when generating the URL, e.g. _format = 'mobile.html'. $nextSeparator = self::findNextSeparator($followingPattern); $regexp = sprintf( '[^%s%s]+', preg_quote($defaultSeparator, self::REGEX_DELIMITER), $defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator, self::REGEX_DELIMITER) : '' ); if (('' !== $nextSeparator && !preg_match('#^\{\w+\}#', $followingPattern)) || '' === $followingPattern) { // When we have a separator, which is disallowed for the variable, we can optimize the regex with a possessive // quantifier. This prevents useless backtracking of PCRE and improves performance by 20% for matching those patterns. // Given the above example, there is no point in backtracking into {page} (that forbids the dot) when a dot must follow // after it. This optimization cannot be applied when the next char is no real separator or when the next variable is // directly adjacent, e.g. '/{x}{y}'. $regexp .= '+'; } } $tokens[] = array('variable', $isSeparator ? $precedingChar : '', $regexp, $varName); $variables[] = $varName; } if ($pos < strlen($pattern)) { $tokens[] = array('text', substr($pattern, $pos)); } // find the first optional token $firstOptional = PHP_INT_MAX; if (!$isHost) { for ($i = count($tokens) - 1; $i >= 0; $i--) { $token = $tokens[$i]; if ('variable' === $token[0] && $route->hasDefault($token[3])) { $firstOptional = $i; } else { break; } } } // compute the matching regexp $regexp = ''; for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) { $regexp .= self::computeRegexp($tokens, $i, $firstOptional); } return array( 'staticPrefix' => 'text' === $tokens[0][0] ? $tokens[0][1] : '', 'regex' => self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s', 'tokens' => array_reverse($tokens), 'variables' => $variables, ); } /** * Returns the next static character in the Route pattern that will serve as a separator. * * @param string $pattern The route pattern * * @return string The next static character that functions as separator (or empty string when none available) */ private static function findNextSeparator($pattern) { if ('' == $pattern) { // return empty string if pattern is empty or false (false which can be returned by substr) return ''; } // first remove all placeholders from the pattern so we can find the next real static character $pattern = preg_replace('#\{\w+\}#', '', $pattern); return isset($pattern[0]) && false !== strpos(static::SEPARATORS, $pattern[0]) ? $pattern[0] : ''; } /** * Computes the regexp used to match a specific token. It can be static text or a subpattern. * * @param array $tokens The route tokens * @param integer $index The index of the current token * @param integer $firstOptional The index of the first optional token * * @return string The regexp pattern for a single token */ private static function computeRegexp(array $tokens, $index, $firstOptional) { $token = $tokens[$index]; if ('text' === $token[0]) { // Text tokens return preg_quote($token[1], self::REGEX_DELIMITER); } else { // Variable tokens if (0 === $index && 0 === $firstOptional) { // When the only token is an optional variable token, the separator is required return sprintf('%s(?P<%s>%s)?', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); } else { $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); if ($index >= $firstOptional) { // Enclose each optional token in a subpattern to make it optional. // "?:" means it is non-capturing, i.e. the portion of the subject string that // matched the optional subpattern is not passed back. $regexp = "(?:$regexp"; $nbTokens = count($tokens); if ($nbTokens - 1 == $index) { // Close the optional subpatterns $regexp .= str_repeat(")?", $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0)); } } return $regexp; } } } } PK]qF>>"Routing/RouteCompilerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * RouteCompilerInterface is the interface that all RouteCompiler classes must implement. * * @author Fabien Potencier */ interface RouteCompilerInterface { /** * Compiles the current route instance. * * @param Route $route A Route instance * * @return CompiledRoute A CompiledRoute instance * * @throws \LogicException If the Route cannot be compiled because the * path or host pattern is invalid */ public static function compile(Route $route); } PK]^==Routing/Route.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * A Route describes a route and its parameters. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class Route implements \Serializable { /** * @var string */ private $path = '/'; /** * @var string */ private $host = ''; /** * @var array */ private $schemes = array(); /** * @var array */ private $methods = array(); /** * @var array */ private $defaults = array(); /** * @var array */ private $requirements = array(); /** * @var array */ private $options = array(); /** * @var null|CompiledRoute */ private $compiled; private $condition; /** * Constructor. * * Available options: * * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) * * @param string $path The path pattern to match * @param array $defaults An array of default parameter values * @param array $requirements An array of requirements for parameters (regexes) * @param array $options An array of options * @param string $host The host pattern to match * @param string|array $schemes A required URI scheme or an array of restricted schemes * @param string|array $methods A required HTTP method or an array of restricted methods * @param string $condition A condition that should evaluate to true for the route to match * * @api */ public function __construct($path, array $defaults = array(), array $requirements = array(), array $options = array(), $host = '', $schemes = array(), $methods = array(), $condition = null) { $this->setPath($path); $this->setDefaults($defaults); $this->setRequirements($requirements); $this->setOptions($options); $this->setHost($host); // The conditions make sure that an initial empty $schemes/$methods does not override the corresponding requirement. // They can be removed when the BC layer is removed. if ($schemes) { $this->setSchemes($schemes); } if ($methods) { $this->setMethods($methods); } $this->setCondition($condition); } public function serialize() { return serialize(array( 'path' => $this->path, 'host' => $this->host, 'defaults' => $this->defaults, 'requirements' => $this->requirements, 'options' => $this->options, 'schemes' => $this->schemes, 'methods' => $this->methods, 'condition' => $this->condition, )); } public function unserialize($data) { $data = unserialize($data); $this->path = $data['path']; $this->host = $data['host']; $this->defaults = $data['defaults']; $this->requirements = $data['requirements']; $this->options = $data['options']; $this->schemes = $data['schemes']; $this->methods = $data['methods']; $this->condition = $data['condition']; } /** * Returns the pattern for the path. * * @return string The pattern * * @deprecated Deprecated in 2.2, to be removed in 3.0. Use getPath instead. */ public function getPattern() { return $this->path; } /** * Sets the pattern for the path. * * This method implements a fluent interface. * * @param string $pattern The path pattern * * @return Route The current Route instance * * @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead. */ public function setPattern($pattern) { return $this->setPath($pattern); } /** * Returns the pattern for the path. * * @return string The path pattern */ public function getPath() { return $this->path; } /** * Sets the pattern for the path. * * This method implements a fluent interface. * * @param string $pattern The path pattern * * @return Route The current Route instance */ public function setPath($pattern) { // A pattern must start with a slash and must not have multiple slashes at the beginning because the // generated path for this route would be confused with a network path, e.g. '//domain.com/path'. $this->path = '/'.ltrim(trim($pattern), '/'); $this->compiled = null; return $this; } /** * Returns the pattern for the host. * * @return string The host pattern */ public function getHost() { return $this->host; } /** * Sets the pattern for the host. * * This method implements a fluent interface. * * @param string $pattern The host pattern * * @return Route The current Route instance */ public function setHost($pattern) { $this->host = (string) $pattern; $this->compiled = null; return $this; } /** * Returns the lowercased schemes this route is restricted to. * So an empty array means that any scheme is allowed. * * @return array The schemes */ public function getSchemes() { return $this->schemes; } /** * Sets the schemes (e.g. 'https') this route is restricted to. * So an empty array means that any scheme is allowed. * * This method implements a fluent interface. * * @param string|array $schemes The scheme or an array of schemes * * @return Route The current Route instance */ public function setSchemes($schemes) { $this->schemes = array_map('strtolower', (array) $schemes); // this is to keep BC and will be removed in a future version if ($this->schemes) { $this->requirements['_scheme'] = implode('|', $this->schemes); } else { unset($this->requirements['_scheme']); } $this->compiled = null; return $this; } /** * Returns the uppercased HTTP methods this route is restricted to. * So an empty array means that any method is allowed. * * @return array The schemes */ public function getMethods() { return $this->methods; } /** * Sets the HTTP methods (e.g. 'POST') this route is restricted to. * So an empty array means that any method is allowed. * * This method implements a fluent interface. * * @param string|array $methods The method or an array of methods * * @return Route The current Route instance */ public function setMethods($methods) { $this->methods = array_map('strtoupper', (array) $methods); // this is to keep BC and will be removed in a future version if ($this->methods) { $this->requirements['_method'] = implode('|', $this->methods); } else { unset($this->requirements['_method']); } $this->compiled = null; return $this; } /** * Returns the options. * * @return array The options */ public function getOptions() { return $this->options; } /** * Sets the options. * * This method implements a fluent interface. * * @param array $options The options * * @return Route The current Route instance */ public function setOptions(array $options) { $this->options = array( 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', ); return $this->addOptions($options); } /** * Adds options. * * This method implements a fluent interface. * * @param array $options The options * * @return Route The current Route instance */ public function addOptions(array $options) { foreach ($options as $name => $option) { $this->options[$name] = $option; } $this->compiled = null; return $this; } /** * Sets an option value. * * This method implements a fluent interface. * * @param string $name An option name * @param mixed $value The option value * * @return Route The current Route instance * * @api */ public function setOption($name, $value) { $this->options[$name] = $value; $this->compiled = null; return $this; } /** * Get an option value. * * @param string $name An option name * * @return mixed The option value or null when not given */ public function getOption($name) { return isset($this->options[$name]) ? $this->options[$name] : null; } /** * Checks if an option has been set * * @param string $name An option name * * @return Boolean true if the option is set, false otherwise */ public function hasOption($name) { return array_key_exists($name, $this->options); } /** * Returns the defaults. * * @return array The defaults */ public function getDefaults() { return $this->defaults; } /** * Sets the defaults. * * This method implements a fluent interface. * * @param array $defaults The defaults * * @return Route The current Route instance */ public function setDefaults(array $defaults) { $this->defaults = array(); return $this->addDefaults($defaults); } /** * Adds defaults. * * This method implements a fluent interface. * * @param array $defaults The defaults * * @return Route The current Route instance */ public function addDefaults(array $defaults) { foreach ($defaults as $name => $default) { $this->defaults[$name] = $default; } $this->compiled = null; return $this; } /** * Gets a default value. * * @param string $name A variable name * * @return mixed The default value or null when not given */ public function getDefault($name) { return isset($this->defaults[$name]) ? $this->defaults[$name] : null; } /** * Checks if a default value is set for the given variable. * * @param string $name A variable name * * @return Boolean true if the default value is set, false otherwise */ public function hasDefault($name) { return array_key_exists($name, $this->defaults); } /** * Sets a default value. * * @param string $name A variable name * @param mixed $default The default value * * @return Route The current Route instance * * @api */ public function setDefault($name, $default) { $this->defaults[$name] = $default; $this->compiled = null; return $this; } /** * Returns the requirements. * * @return array The requirements */ public function getRequirements() { return $this->requirements; } /** * Sets the requirements. * * This method implements a fluent interface. * * @param array $requirements The requirements * * @return Route The current Route instance */ public function setRequirements(array $requirements) { $this->requirements = array(); return $this->addRequirements($requirements); } /** * Adds requirements. * * This method implements a fluent interface. * * @param array $requirements The requirements * * @return Route The current Route instance */ public function addRequirements(array $requirements) { foreach ($requirements as $key => $regex) { $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); } $this->compiled = null; return $this; } /** * Returns the requirement for the given key. * * @param string $key The key * * @return string|null The regex or null when not given */ public function getRequirement($key) { return isset($this->requirements[$key]) ? $this->requirements[$key] : null; } /** * Checks if a requirement is set for the given key. * * @param string $key A variable name * * @return Boolean true if a requirement is specified, false otherwise */ public function hasRequirement($key) { return array_key_exists($key, $this->requirements); } /** * Sets a requirement for the given key. * * @param string $key The key * @param string $regex The regex * * @return Route The current Route instance * * @api */ public function setRequirement($key, $regex) { $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); $this->compiled = null; return $this; } /** * Returns the condition. * * @return string The condition */ public function getCondition() { return $this->condition; } /** * Sets the condition. * * This method implements a fluent interface. * * @param string $condition The condition * * @return Route The current Route instance */ public function setCondition($condition) { $this->condition = (string) $condition; $this->compiled = null; return $this; } /** * Compiles the route. * * @return CompiledRoute A CompiledRoute instance * * @throws \LogicException If the Route cannot be compiled because the * path or host pattern is invalid * * @see RouteCompiler which is responsible for the compilation process */ public function compile() { if (null !== $this->compiled) { return $this->compiled; } $class = $this->getOption('compiler_class'); return $this->compiled = $class::compile($this); } private function sanitizeRequirement($key, $regex) { if (!is_string($regex)) { throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" must be a string.', $key)); } if ('' !== $regex && '^' === $regex[0]) { $regex = (string) substr($regex, 1); // returns false for a single character } if ('$' === substr($regex, -1)) { $regex = substr($regex, 0, -1); } if ('' === $regex) { throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key)); } // this is to keep BC and will be removed in a future version if ('_scheme' === $key) { $this->setSchemes(explode('|', $regex)); } elseif ('_method' === $key) { $this->setMethods(explode('|', $regex)); } return $regex; } } PK] ff3Routing/Matcher/RedirectableUrlMatcherInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; /** * RedirectableUrlMatcherInterface knows how to redirect the user. * * @author Fabien Potencier * * @api */ interface RedirectableUrlMatcherInterface { /** * Redirects the user to another URL. * * @param string $path The path info to redirect to. * @param string $route The route name that matched * @param string|null $scheme The URL scheme (null to keep the current one) * * @return array An array of parameters * * @api */ public function redirect($path, $route, $scheme = null); } PK]''Routing/Matcher/TraceableUrlMatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Exception\ExceptionInterface; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** * TraceableUrlMatcher helps debug path info matching by tracing the match. * * @author Fabien Potencier */ class TraceableUrlMatcher extends UrlMatcher { const ROUTE_DOES_NOT_MATCH = 0; const ROUTE_ALMOST_MATCHES = 1; const ROUTE_MATCHES = 2; protected $traces; public function getTraces($pathinfo) { $this->traces = array(); try { $this->match($pathinfo); } catch (ExceptionInterface $e) { } return $this->traces; } protected function matchCollection($pathinfo, RouteCollection $routes) { foreach ($routes as $name => $route) { $compiledRoute = $route->compile(); if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) { // does it match without any requirements? $r = new Route($route->getPath(), $route->getDefaults(), array(), $route->getOptions()); $cr = $r->compile(); if (!preg_match($cr->getRegex(), $pathinfo)) { $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); continue; } foreach ($route->getRequirements() as $n => $regex) { $r = new Route($route->getPath(), $route->getDefaults(), array($n => $regex), $route->getOptions()); $cr = $r->compile(); if (in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) { $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route); continue 2; } } continue; } // check host requirement $hostMatches = array(); if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; } // check HTTP method requirement if ($req = $route->getRequirement('_method')) { // HEAD and GET are equivalent as per RFC if ('HEAD' === $method = $this->context->getMethod()) { $method = 'GET'; } if (!in_array($method, $req = explode('|', strtoupper($req)))) { $this->allow = array_merge($this->allow, $req); $this->addTrace(sprintf('Method "%s" does not match the requirement ("%s")', $this->context->getMethod(), implode(', ', $req)), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; } } // check condition if ($condition = $route->getCondition()) { if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request))) { $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $condition), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; } } // check HTTP scheme requirement if ($scheme = $route->getRequirement('_scheme')) { if ($this->context->getScheme() !== $scheme) { $this->addTrace(sprintf('Scheme "%s" does not match the requirement ("%s"); the user will be redirected', $this->context->getScheme(), $scheme), self::ROUTE_ALMOST_MATCHES, $name, $route); return true; } } $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); return true; } } private function addTrace($log, $level = self::ROUTE_DOES_NOT_MATCH, $name = null, $route = null) { $this->traces[] = array( 'log' => $log, 'name' => $name, 'level' => $level, 'path' => null !== $route ? $route->getPath() : null, ); } } PK]`u+Routing/Matcher/RequestMatcherInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Exception\MethodNotAllowedException; /** * RequestMatcherInterface is the interface that all request matcher classes must implement. * * @author Fabien Potencier */ interface RequestMatcherInterface { /** * Tries to match a request with a set of routes. * * If the matcher can not find information, it must throw one of the exceptions documented * below. * * @param Request $request The request to match * * @return array An array of parameters * * @throws ResourceNotFoundException If no matching resource could be found * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed */ public function matchRequest(Request $request); } PK][zdd*Routing/Matcher/RedirectableUrlMatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Route; /** * @author Fabien Potencier * * @api */ abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface { /** * {@inheritdoc} */ public function match($pathinfo) { try { $parameters = parent::match($pathinfo); } catch (ResourceNotFoundException $e) { if ('/' === substr($pathinfo, -1) || !in_array($this->context->getMethod(), array('HEAD', 'GET'))) { throw $e; } try { parent::match($pathinfo.'/'); return $this->redirect($pathinfo.'/', null); } catch (ResourceNotFoundException $e2) { throw $e; } } return $parameters; } /** * {@inheritDoc} */ protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { return array(self::REQUIREMENT_MISMATCH, null); } // check HTTP scheme requirement $scheme = $route->getRequirement('_scheme'); if ($scheme && $this->context->getScheme() !== $scheme) { return array(self::ROUTE_MATCH, $this->redirect($pathinfo, $name, $scheme)); } return array(self::REQUIREMENT_MATCH, null); } } PK]YIWW&Routing/Matcher/Dumper/DumperRoute.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\Route; /** * Container for a Route. * * @author Arnaud Le Blanc */ class DumperRoute { /** * @var string */ private $name; /** * @var Route */ private $route; /** * Constructor. * * @param string $name The route name * @param Route $route The route */ public function __construct($name, Route $route) { $this->name = $name; $this->route = $route; } /** * Returns the route name. * * @return string The route name */ public function getName() { return $this->name; } /** * Returns the route. * * @return Route The route */ public function getRoute() { return $this->route; } } PK]x}44+Routing/Matcher/Dumper/PhpMatcherDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; /** * PhpMatcherDumper creates a PHP class able to match URLs for a given set of routes. * * @author Fabien Potencier * @author Tobias Schultze * @author Arnaud Le Blanc */ class PhpMatcherDumper extends MatcherDumper { private $expressionLanguage; /** * Dumps a set of routes to a PHP class. * * Available options: * * * class: The class name * * base_class: The base class name * * @param array $options An array of options * * @return string A PHP class representing the matcher class */ public function dump(array $options = array()) { $options = array_replace(array( 'class' => 'ProjectUrlMatcher', 'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', ), $options); // trailing slash support is only enabled if we know how to redirect the user $interfaces = class_implements($options['base_class']); $supportsRedirections = isset($interfaces['Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface']); return <<context = \$context; } {$this->generateMatchMethod($supportsRedirections)} } EOF; } /** * Generates the code for the match method implementing UrlMatcherInterface. * * @param Boolean $supportsRedirections Whether redirections are supported by the base class * * @return string Match method as PHP code */ private function generateMatchMethod($supportsRedirections) { $code = rtrim($this->compileRoutes($this->getRoutes(), $supportsRedirections), "\n"); return <<context; \$request = \$this->request; $code throw 0 < count(\$allow) ? new MethodNotAllowedException(array_unique(\$allow)) : new ResourceNotFoundException(); } EOF; } /** * Generates PHP code to match a RouteCollection with all its routes. * * @param RouteCollection $routes A RouteCollection instance * @param Boolean $supportsRedirections Whether redirections are supported by the base class * * @return string PHP code */ private function compileRoutes(RouteCollection $routes, $supportsRedirections) { $fetchedHost = false; $groups = $this->groupRoutesByHostRegex($routes); $code = ''; foreach ($groups as $collection) { if (null !== $regex = $collection->getAttribute('host_regex')) { if (!$fetchedHost) { $code .= " \$host = \$this->context->getHost();\n\n"; $fetchedHost = true; } $code .= sprintf(" if (preg_match(%s, \$host, \$hostMatches)) {\n", var_export($regex, true)); } $tree = $this->buildPrefixTree($collection); $groupCode = $this->compilePrefixRoutes($tree, $supportsRedirections); if (null !== $regex) { // apply extra indention at each line (except empty ones) $groupCode = preg_replace('/^.{2,}$/m', ' $0', $groupCode); $code .= $groupCode; $code .= " }\n\n"; } else { $code .= $groupCode; } } return $code; } /** * Generates PHP code recursively to match a tree of routes * * @param DumperPrefixCollection $collection A DumperPrefixCollection instance * @param Boolean $supportsRedirections Whether redirections are supported by the base class * @param string $parentPrefix Prefix of the parent collection * * @return string PHP code */ private function compilePrefixRoutes(DumperPrefixCollection $collection, $supportsRedirections, $parentPrefix = '') { $code = ''; $prefix = $collection->getPrefix(); $optimizable = 1 < strlen($prefix) && 1 < count($collection->all()); $optimizedPrefix = $parentPrefix; if ($optimizable) { $optimizedPrefix = $prefix; $code .= sprintf(" if (0 === strpos(\$pathinfo, %s)) {\n", var_export($prefix, true)); } foreach ($collection as $route) { if ($route instanceof DumperCollection) { $code .= $this->compilePrefixRoutes($route, $supportsRedirections, $optimizedPrefix); } else { $code .= $this->compileRoute($route->getRoute(), $route->getName(), $supportsRedirections, $optimizedPrefix)."\n"; } } if ($optimizable) { $code .= " }\n\n"; // apply extra indention at each line (except empty ones) $code = preg_replace('/^.{2,}$/m', ' $0', $code); } return $code; } /** * Compiles a single Route to PHP code used to match it against the path info. * * @param Route $route A Route instance * @param string $name The name of the Route * @param Boolean $supportsRedirections Whether redirections are supported by the base class * @param string|null $parentPrefix The prefix of the parent collection used to optimize the code * * @return string PHP code * * @throws \LogicException */ private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null) { $code = ''; $compiledRoute = $route->compile(); $conditions = array(); $hasTrailingSlash = false; $matches = false; $hostMatches = false; $methods = array(); if ($req = $route->getRequirement('_method')) { $methods = explode('|', strtoupper($req)); // GET and HEAD are equivalent if (in_array('GET', $methods) && !in_array('HEAD', $methods)) { $methods[] = 'HEAD'; } } $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods)); if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P.*?)\$\1#', $compiledRoute->getRegex(), $m)) { if ($supportsTrailingSlash && substr($m['url'], -1) === '/') { $conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true)); $hasTrailingSlash = true; } else { $conditions[] = sprintf("\$pathinfo === %s", var_export(str_replace('\\', '', $m['url']), true)); } } else { if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() !== $parentPrefix) { $conditions[] = sprintf("0 === strpos(\$pathinfo, %s)", var_export($compiledRoute->getStaticPrefix(), true)); } $regex = $compiledRoute->getRegex(); if ($supportsTrailingSlash && $pos = strpos($regex, '/$')) { $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2); $hasTrailingSlash = true; } $conditions[] = sprintf("preg_match(%s, \$pathinfo, \$matches)", var_export($regex, true)); $matches = true; } if ($compiledRoute->getHostVariables()) { $hostMatches = true; } if ($route->getCondition()) { $conditions[] = $this->getExpressionLanguage()->compile($route->getCondition(), array('context', 'request')); } $conditions = implode(' && ', $conditions); $code .= <<context->getMethod() != '$methods[0]') { \$allow[] = '$methods[0]'; goto $gotoname; } EOF; } else { $methods = implode("', '", $methods); $code .= <<context->getMethod(), array('$methods'))) { \$allow = array_merge(\$allow, array('$methods')); goto $gotoname; } EOF; } } if ($hasTrailingSlash) { $code .= <<redirect(\$pathinfo.'/', '$name'); } EOF; } if ($scheme = $route->getRequirement('_scheme')) { if (!$supportsRedirections) { throw new \LogicException('The "_scheme" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.'); } $code .= <<context->getScheme() !== '$scheme') { return \$this->redirect(\$pathinfo, '$name', '$scheme'); } EOF; } // optimize parameters array if ($matches || $hostMatches) { $vars = array(); if ($hostMatches) { $vars[] = '$hostMatches'; } if ($matches) { $vars[] = '$matches'; } $vars[] = "array('_route' => '$name')"; $code .= sprintf(" return \$this->mergeDefaults(array_replace(%s), %s);\n" , implode(', ', $vars), str_replace("\n", '', var_export($route->getDefaults(), true))); } elseif ($route->getDefaults()) { $code .= sprintf(" return %s;\n", str_replace("\n", '', var_export(array_replace($route->getDefaults(), array('_route' => $name)), true))); } else { $code .= sprintf(" return array('_route' => '%s');\n", $name); } $code .= " }\n"; if ($methods) { $code .= " $gotoname:\n"; } return $code; } /** * Groups consecutive routes having the same host regex. * * The result is a collection of collections of routes having the same host regex. * * @param RouteCollection $routes A flat RouteCollection * * @return DumperCollection A collection with routes grouped by host regex in sub-collections */ private function groupRoutesByHostRegex(RouteCollection $routes) { $groups = new DumperCollection(); $currentGroup = new DumperCollection(); $currentGroup->setAttribute('host_regex', null); $groups->add($currentGroup); foreach ($routes as $name => $route) { $hostRegex = $route->compile()->getHostRegex(); if ($currentGroup->getAttribute('host_regex') !== $hostRegex) { $currentGroup = new DumperCollection(); $currentGroup->setAttribute('host_regex', $hostRegex); $groups->add($currentGroup); } $currentGroup->add(new DumperRoute($name, $route)); } return $groups; } /** * Organizes the routes into a prefix tree. * * Routes order is preserved such that traversing the tree will traverse the * routes in the origin order. * * @param DumperCollection $collection A collection of routes * * @return DumperPrefixCollection */ private function buildPrefixTree(DumperCollection $collection) { $tree = new DumperPrefixCollection(); $current = $tree; foreach ($collection as $route) { $current = $current->addPrefixRoute($route); } $tree->mergeSlashNodes(); return $tree; } private function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(); } return $this->expressionLanguage; } } PK]?|{(Routing/Matcher/Dumper/MatcherDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\RouteCollection; /** * MatcherDumper is the abstract class for all built-in matcher dumpers. * * @author Fabien Potencier */ abstract class MatcherDumper implements MatcherDumperInterface { /** * @var RouteCollection */ private $routes; /** * Constructor. * * @param RouteCollection $routes The RouteCollection to dump */ public function __construct(RouteCollection $routes) { $this->routes = $routes; } /** * {@inheritdoc} */ public function getRoutes() { return $this->routes; } } PK]( 1Routing/Matcher/Dumper/MatcherDumperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\RouteCollection; /** * MatcherDumperInterface is the interface that all matcher dumper classes must implement. * * @author Fabien Potencier */ interface MatcherDumperInterface { /** * Dumps a set of routes to a string representation of executable code * that can then be used to match a request against these routes. * * @param array $options An array of options * * @return string Executable code */ public function dump(array $options = array()); /** * Gets the routes to dump. * * @return RouteCollection A RouteCollection instance */ public function getRoutes(); } PK]N 1Routing/Matcher/Dumper/DumperPrefixCollection.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; /** * Prefix tree of routes preserving routes order. * * @author Arnaud Le Blanc */ class DumperPrefixCollection extends DumperCollection { /** * @var string */ private $prefix = ''; /** * Returns the prefix. * * @return string The prefix */ public function getPrefix() { return $this->prefix; } /** * Sets the prefix. * * @param string $prefix The prefix */ public function setPrefix($prefix) { $this->prefix = $prefix; } /** * Adds a route in the tree. * * @param DumperRoute $route The route * * @return DumperPrefixCollection The node the route was added to * * @throws \LogicException */ public function addPrefixRoute(DumperRoute $route) { $prefix = $route->getRoute()->compile()->getStaticPrefix(); for ($collection = $this; null !== $collection; $collection = $collection->getParent()) { // Same prefix, add to current leave if ($collection->prefix === $prefix) { $collection->add($route); return $collection; } // Prefix starts with route's prefix if ('' === $collection->prefix || 0 === strpos($prefix, $collection->prefix)) { $child = new DumperPrefixCollection(); $child->setPrefix(substr($prefix, 0, strlen($collection->prefix)+1)); $collection->add($child); return $child->addPrefixRoute($route); } } // Reached only if the root has a non empty prefix throw new \LogicException("The collection root must not have a prefix"); } /** * Merges nodes whose prefix ends with a slash * * Children of a node whose prefix ends with a slash are moved to the parent node */ public function mergeSlashNodes() { $children = array(); foreach ($this as $child) { if ($child instanceof self) { $child->mergeSlashNodes(); if ('/' === substr($child->prefix, -1)) { $children = array_merge($children, $child->all()); } else { $children[] = $child; } } else { $children[] = $child; } } $this->setAll($children); } } PK]`+Routing/Matcher/Dumper/DumperCollection.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; /** * Collection of routes. * * @author Arnaud Le Blanc */ class DumperCollection implements \IteratorAggregate { /** * @var DumperCollection|null */ private $parent; /** * @var (DumperCollection|DumperRoute)[] */ private $children = array(); /** * @var array */ private $attributes = array(); /** * Returns the children routes and collections. * * @return (DumperCollection|DumperRoute)[] Array of DumperCollection|DumperRoute */ public function all() { return $this->children; } /** * Adds a route or collection * * @param DumperRoute|DumperCollection The route or collection */ public function add($child) { if ($child instanceof DumperCollection) { $child->setParent($this); } $this->children[] = $child; } /** * Sets children. * * @param array $children The children */ public function setAll(array $children) { foreach ($children as $child) { if ($child instanceof DumperCollection) { $child->setParent($this); } } $this->children = $children; } /** * Returns an iterator over the children. * * @return \Iterator The iterator */ public function getIterator() { return new \ArrayIterator($this->children); } /** * Returns the root of the collection. * * @return DumperCollection The root collection */ public function getRoot() { return (null !== $this->parent) ? $this->parent->getRoot() : $this; } /** * Returns the parent collection. * * @return DumperCollection|null The parent collection or null if the collection has no parent */ protected function getParent() { return $this->parent; } /** * Sets the parent collection. * * @param DumperCollection $parent The parent collection */ protected function setParent(DumperCollection $parent) { $this->parent = $parent; } /** * Returns true if the attribute is defined. * * @param string $name The attribute name * * @return Boolean true if the attribute is defined, false otherwise */ public function hasAttribute($name) { return array_key_exists($name, $this->attributes); } /** * Returns an attribute by name. * * @param string $name The attribute name * @param mixed $default Default value is the attribute doesn't exist * * @return mixed The attribute value */ public function getAttribute($name, $default = null) { return $this->hasAttribute($name) ? $this->attributes[$name] : $default; } /** * Sets an attribute by name. * * @param string $name The attribute name * @param mixed $value The attribute value */ public function setAttribute($name, $value) { $this->attributes[$name] = $value; } /** * Sets multiple attributes. * * @param array $attributes The attributes */ public function setAttributes($attributes) { $this->attributes = $attributes; } } PK] bz#z#.Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\Route; /** * Dumps a set of Apache mod_rewrite rules. * * @author Fabien Potencier * @author Kris Wallsmith */ class ApacheMatcherDumper extends MatcherDumper { /** * Dumps a set of Apache mod_rewrite rules. * * Available options: * * * script_name: The script name (app.php by default) * * base_uri: The base URI ("" by default) * * @param array $options An array of options * * @return string A string to be used as Apache rewrite rules * * @throws \LogicException When the route regex is invalid */ public function dump(array $options = array()) { $options = array_merge(array( 'script_name' => 'app.php', 'base_uri' => '', ), $options); $options['script_name'] = self::escape($options['script_name'], ' ', '\\'); $rules = array("# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]"); $methodVars = array(); $hostRegexUnique = 0; $prevHostRegex = ''; foreach ($this->getRoutes()->all() as $name => $route) { if ($route->getCondition()) { throw new \LogicException(sprintf('Unable to dump the routes for Apache as route "%s" has a condition.', $name)); } $compiledRoute = $route->compile(); $hostRegex = $compiledRoute->getHostRegex(); if (null !== $hostRegex && $prevHostRegex !== $hostRegex) { $prevHostRegex = $hostRegex; $hostRegexUnique++; $rule = array(); $regex = $this->regexToApacheRegex($hostRegex); $regex = self::escape($regex, ' ', '\\'); $rule[] = sprintf('RewriteCond %%{HTTP:Host} %s', $regex); $variables = array(); $variables[] = sprintf('E=__ROUTING_host_%s:1', $hostRegexUnique); foreach ($compiledRoute->getHostVariables() as $i => $variable) { $variables[] = sprintf('E=__ROUTING_host_%s_%s:%%%d', $hostRegexUnique, $variable, $i+1); } $variables = implode(',', $variables); $rule[] = sprintf('RewriteRule .? - [%s]', $variables); $rules[] = implode("\n", $rule); } $rules[] = $this->dumpRoute($name, $route, $options, $hostRegexUnique); if ($req = $route->getRequirement('_method')) { $methods = explode('|', strtoupper($req)); $methodVars = array_merge($methodVars, $methods); } } if (0 < count($methodVars)) { $rule = array('# 405 Method Not Allowed'); $methodVars = array_values(array_unique($methodVars)); if (in_array('GET', $methodVars) && !in_array('HEAD', $methodVars)) { $methodVars[] = 'HEAD'; } foreach ($methodVars as $i => $methodVar) { $rule[] = sprintf('RewriteCond %%{ENV:_ROUTING__allow_%s} =1%s', $methodVar, isset($methodVars[$i + 1]) ? ' [OR]' : ''); } $rule[] = sprintf('RewriteRule .* %s [QSA,L]', $options['script_name']); $rules[] = implode("\n", $rule); } return implode("\n\n", $rules)."\n"; } /** * Dumps a single route * * @param string $name Route name * @param Route $route The route * @param array $options Options * @param bool $hostRegexUnique Unique identifier for the host regex * * @return string The compiled route */ private function dumpRoute($name, $route, array $options, $hostRegexUnique) { $compiledRoute = $route->compile(); // prepare the apache regex $regex = $this->regexToApacheRegex($compiledRoute->getRegex()); $regex = '^'.self::escape(preg_quote($options['base_uri']).substr($regex, 1), ' ', '\\'); $methods = $this->getRouteMethods($route); $hasTrailingSlash = (!$methods || in_array('HEAD', $methods)) && '/$' === substr($regex, -2) && '^/$' !== $regex; $variables = array('E=_ROUTING_route:'.$name); foreach ($compiledRoute->getHostVariables() as $variable) { $variables[] = sprintf('E=_ROUTING_param_%s:%%{ENV:__ROUTING_host_%s_%s}', $variable, $hostRegexUnique, $variable); } foreach ($compiledRoute->getPathVariables() as $i => $variable) { $variables[] = 'E=_ROUTING_param_'.$variable.':%'.($i + 1); } foreach ($this->normalizeValues($route->getDefaults()) as $key => $value) { $variables[] = 'E=_ROUTING_default_'.$key.':'.strtr($value, array( ':' => '\\:', '=' => '\\=', '\\' => '\\\\', ' ' => '\\ ', )); } $variables = implode(',', $variables); $rule = array("# $name"); // method mismatch if (0 < count($methods)) { $allow = array(); foreach ($methods as $method) { $allow[] = 'E=_ROUTING_allow_'.$method.':1'; } if ($compiledRoute->getHostRegex()) { $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique); } $rule[] = "RewriteCond %{REQUEST_URI} $regex"; $rule[] = sprintf("RewriteCond %%{REQUEST_METHOD} !^(%s)$ [NC]", implode('|', $methods)); $rule[] = sprintf('RewriteRule .* - [S=%d,%s]', $hasTrailingSlash ? 2 : 1, implode(',', $allow)); } // redirect with trailing slash appended if ($hasTrailingSlash) { if ($compiledRoute->getHostRegex()) { $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique); } $rule[] = 'RewriteCond %{REQUEST_URI} '.substr($regex, 0, -2).'$'; $rule[] = 'RewriteRule .* $0/ [QSA,L,R=301]'; } // the main rule if ($compiledRoute->getHostRegex()) { $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique); } $rule[] = "RewriteCond %{REQUEST_URI} $regex"; $rule[] = "RewriteRule .* {$options['script_name']} [QSA,L,$variables]"; return implode("\n", $rule); } /** * Returns methods allowed for a route * * @param Route $route The route * * @return array The methods */ private function getRouteMethods(Route $route) { $methods = array(); if ($req = $route->getRequirement('_method')) { $methods = explode('|', strtoupper($req)); // GET and HEAD are equivalent if (in_array('GET', $methods) && !in_array('HEAD', $methods)) { $methods[] = 'HEAD'; } } return $methods; } /** * Converts a regex to make it suitable for mod_rewrite * * @param string $regex The regex * * @return string The converted regex */ private function regexToApacheRegex($regex) { $regexPatternEnd = strrpos($regex, $regex[0]); return preg_replace('/\?P<.+?>/', '', substr($regex, 1, $regexPatternEnd - 1)); } /** * Escapes a string. * * @param string $string The string to be escaped * @param string $char The character to be escaped * @param string $with The character to be used for escaping * * @return string The escaped string */ private static function escape($string, $char, $with) { $escaped = false; $output = ''; foreach (str_split($string) as $symbol) { if ($escaped) { $output .= $symbol; $escaped = false; continue; } if ($symbol === $char) { $output .= $with.$char; continue; } if ($symbol === $with) { $escaped = true; } $output .= $symbol; } return $output; } /** * Normalizes an array of values. * * @param array $values * * @return string[] */ private function normalizeValues(array $values) { $normalizedValues = array(); foreach ($values as $key => $value) { if (is_array($value)) { foreach ($value as $index => $bit) { $normalizedValues[sprintf('%s[%s]', $key, $index)] = $bit; } } else { $normalizedValues[$key] = (string) $value; } } return $normalizedValues; } } PK]q q $Routing/Matcher/ApacheUrlMatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Exception\MethodNotAllowedException; /** * ApacheUrlMatcher matches URL based on Apache mod_rewrite matching (see ApacheMatcherDumper). * * @author Fabien Potencier * @author Arnaud Le Blanc */ class ApacheUrlMatcher extends UrlMatcher { /** * Tries to match a URL based on Apache mod_rewrite matching. * * Returns false if no route matches the URL. * * @param string $pathinfo The pathinfo to be parsed * * @return array An array of parameters * * @throws MethodNotAllowedException If the current method is not allowed */ public function match($pathinfo) { $parameters = array(); $defaults = array(); $allow = array(); $route = null; foreach ($this->denormalizeValues($_SERVER) as $key => $value) { $name = $key; // skip non-routing variables // this improves performance when $_SERVER contains many usual // variables like HTTP_*, DOCUMENT_ROOT, REQUEST_URI, ... if (false === strpos($name, '_ROUTING_')) { continue; } while (0 === strpos($name, 'REDIRECT_')) { $name = substr($name, 9); } // expect _ROUTING__ // or _ROUTING_ if (0 !== strpos($name, '_ROUTING_')) { continue; } if (false !== $pos = strpos($name, '_', 9)) { $type = substr($name, 9, $pos-9); $name = substr($name, $pos+1); } else { $type = substr($name, 9); } if ('param' === $type) { if ('' !== $value) { $parameters[$name] = $value; } } elseif ('default' === $type) { $defaults[$name] = $value; } elseif ('route' === $type) { $route = $value; } elseif ('allow' === $type) { $allow[] = $name; } unset($_SERVER[$key]); } if (null !== $route) { $parameters['_route'] = $route; return $this->mergeDefaults($parameters, $defaults); } elseif (0 < count($allow)) { throw new MethodNotAllowedException($allow); } else { return parent::match($pathinfo); } } /** * Denormalizes an array of values. * * @param string[] $values * * @return array */ private function denormalizeValues(array $values) { $normalizedValues = array(); foreach ($values as $key => $value) { if (preg_match('~^(.*)\[(\d+)\]$~', $key, $matches)) { if (!isset($normalizedValues[$matches[1]])) { $normalizedValues[$matches[1]] = array(); } $normalizedValues[$matches[1]][(int) $matches[2]] = $value; } else { $normalizedValues[$key] = $value; } } return $normalizedValues; } } PK]GjC""Routing/Matcher/UrlMatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; /** * UrlMatcher matches URL based on a set of routes. * * @author Fabien Potencier * * @api */ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface { const REQUIREMENT_MATCH = 0; const REQUIREMENT_MISMATCH = 1; const ROUTE_MATCH = 2; /** * @var RequestContext */ protected $context; /** * @var array */ protected $allow = array(); /** * @var RouteCollection */ protected $routes; protected $request; protected $expressionLanguage; /** * Constructor. * * @param RouteCollection $routes A RouteCollection instance * @param RequestContext $context The context * * @api */ public function __construct(RouteCollection $routes, RequestContext $context) { $this->routes = $routes; $this->context = $context; } /** * {@inheritdoc} */ public function setContext(RequestContext $context) { $this->context = $context; } /** * {@inheritdoc} */ public function getContext() { return $this->context; } /** * {@inheritdoc} */ public function match($pathinfo) { $this->allow = array(); if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) { return $ret; } throw 0 < count($this->allow) ? new MethodNotAllowedException(array_unique(array_map('strtoupper', $this->allow))) : new ResourceNotFoundException(); } /** * {@inheritdoc} */ public function matchRequest(Request $request) { $this->request = $request; $ret = $this->match($request->getPathInfo()); $this->request = null; return $ret; } /** * Tries to match a URL with a set of routes. * * @param string $pathinfo The path info to be parsed * @param RouteCollection $routes The set of routes * * @return array An array of parameters * * @throws ResourceNotFoundException If the resource could not be found * @throws MethodNotAllowedException If the resource was found but the request method is not allowed */ protected function matchCollection($pathinfo, RouteCollection $routes) { foreach ($routes as $name => $route) { $compiledRoute = $route->compile(); // check the static prefix of the URL first. Only use the more expensive preg_match when it matches if ('' !== $compiledRoute->getStaticPrefix() && 0 !== strpos($pathinfo, $compiledRoute->getStaticPrefix())) { continue; } if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) { continue; } $hostMatches = array(); if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { continue; } // check HTTP method requirement if ($req = $route->getRequirement('_method')) { // HEAD and GET are equivalent as per RFC if ('HEAD' === $method = $this->context->getMethod()) { $method = 'GET'; } if (!in_array($method, $req = explode('|', strtoupper($req)))) { $this->allow = array_merge($this->allow, $req); continue; } } $status = $this->handleRouteRequirements($pathinfo, $name, $route); if (self::ROUTE_MATCH === $status[0]) { return $status[1]; } if (self::REQUIREMENT_MISMATCH === $status[0]) { continue; } return $this->getAttributes($route, $name, array_replace($matches, $hostMatches)); } } /** * Returns an array of values to use as request attributes. * * As this method requires the Route object, it is not available * in matchers that do not have access to the matched Route instance * (like the PHP and Apache matcher dumpers). * * @param Route $route The route we are matching against * @param string $name The name of the route * @param array $attributes An array of attributes from the matcher * * @return array An array of parameters */ protected function getAttributes(Route $route, $name, array $attributes) { $attributes['_route'] = $name; return $this->mergeDefaults($attributes, $route->getDefaults()); } /** * Handles specific route requirements. * * @param string $pathinfo The path * @param string $name The route name * @param Route $route The route * * @return array The first element represents the status, the second contains additional information */ protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { return array(self::REQUIREMENT_MISMATCH, null); } // check HTTP scheme requirement $scheme = $route->getRequirement('_scheme'); $status = $scheme && $scheme !== $this->context->getScheme() ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH; return array($status, null); } /** * Get merged default parameters. * * @param array $params The parameters * @param array $defaults The defaults * * @return array Merged default parameters */ protected function mergeDefaults($params, $defaults) { foreach ($params as $key => $value) { if (!is_int($key)) { $defaults[$key] = $value; } } return $defaults; } protected function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(); } return $this->expressionLanguage; } } PK] ڗ'Routing/Matcher/UrlMatcherInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\RequestContextAwareInterface; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Exception\MethodNotAllowedException; /** * UrlMatcherInterface is the interface that all URL matcher classes must implement. * * @author Fabien Potencier * * @api */ interface UrlMatcherInterface extends RequestContextAwareInterface { /** * Tries to match a URL path with a set of routes. * * If the matcher can not find information, it must throw one of the exceptions documented * below. * * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded) * * @return array An array of parameters * * @throws ResourceNotFoundException If the resource could not be found * @throws MethodNotAllowedException If the resource was found but the request method is not allowed * * @api */ public function match($pathinfo); } PK]hRouting/RequestContext.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\HttpFoundation\Request; /** * Holds information about the current request. * * @author Fabien Potencier * * @api */ class RequestContext { private $baseUrl; private $pathInfo; private $method; private $host; private $scheme; private $httpPort; private $httpsPort; private $queryString; /** * @var array */ private $parameters = array(); /** * Constructor. * * @param string $baseUrl The base URL * @param string $method The HTTP method * @param string $host The HTTP host name * @param string $scheme The HTTP scheme * @param integer $httpPort The HTTP port * @param integer $httpsPort The HTTPS port * @param string $path The path * @param string $queryString The query string * * @api */ public function __construct($baseUrl = '', $method = 'GET', $host = 'localhost', $scheme = 'http', $httpPort = 80, $httpsPort = 443, $path = '/', $queryString = '') { $this->baseUrl = $baseUrl; $this->method = strtoupper($method); $this->host = $host; $this->scheme = strtolower($scheme); $this->httpPort = $httpPort; $this->httpsPort = $httpsPort; $this->pathInfo = $path; $this->queryString = $queryString; } public function fromRequest(Request $request) { $this->setBaseUrl($request->getBaseUrl()); $this->setPathInfo($request->getPathInfo()); $this->setMethod($request->getMethod()); $this->setHost($request->getHost()); $this->setScheme($request->getScheme()); $this->setHttpPort($request->isSecure() ? $this->httpPort : $request->getPort()); $this->setHttpsPort($request->isSecure() ? $request->getPort() : $this->httpsPort); $this->setQueryString($request->server->get('QUERY_STRING')); } /** * Gets the base URL. * * @return string The base URL */ public function getBaseUrl() { return $this->baseUrl; } /** * Sets the base URL. * * @param string $baseUrl The base URL * * @api */ public function setBaseUrl($baseUrl) { $this->baseUrl = $baseUrl; } /** * Gets the path info. * * @return string The path info */ public function getPathInfo() { return $this->pathInfo; } /** * Sets the path info. * * @param string $pathInfo The path info */ public function setPathInfo($pathInfo) { $this->pathInfo = $pathInfo; } /** * Gets the HTTP method. * * The method is always an uppercased string. * * @return string The HTTP method */ public function getMethod() { return $this->method; } /** * Sets the HTTP method. * * @param string $method The HTTP method * * @api */ public function setMethod($method) { $this->method = strtoupper($method); } /** * Gets the HTTP host. * * @return string The HTTP host */ public function getHost() { return $this->host; } /** * Sets the HTTP host. * * @param string $host The HTTP host * * @api */ public function setHost($host) { $this->host = $host; } /** * Gets the HTTP scheme. * * @return string The HTTP scheme */ public function getScheme() { return $this->scheme; } /** * Sets the HTTP scheme. * * @param string $scheme The HTTP scheme * * @api */ public function setScheme($scheme) { $this->scheme = strtolower($scheme); } /** * Gets the HTTP port. * * @return string The HTTP port */ public function getHttpPort() { return $this->httpPort; } /** * Sets the HTTP port. * * @param string $httpPort The HTTP port * * @api */ public function setHttpPort($httpPort) { $this->httpPort = $httpPort; } /** * Gets the HTTPS port. * * @return string The HTTPS port */ public function getHttpsPort() { return $this->httpsPort; } /** * Sets the HTTPS port. * * @param string $httpsPort The HTTPS port * * @api */ public function setHttpsPort($httpsPort) { $this->httpsPort = $httpsPort; } /** * Gets the query string. * * @return string The query string */ public function getQueryString() { return $this->queryString; } /** * Sets the query string. * * @param string $queryString The query string * * @api */ public function setQueryString($queryString) { $this->queryString = $queryString; } /** * Returns the parameters. * * @return array The parameters */ public function getParameters() { return $this->parameters; } /** * Sets the parameters. * * This method implements a fluent interface. * * @param array $parameters The parameters * * @return Route The current Route instance */ public function setParameters(array $parameters) { $this->parameters = $parameters; return $this; } /** * Gets a parameter value. * * @param string $name A parameter name * * @return mixed The parameter value */ public function getParameter($name) { return isset($this->parameters[$name]) ? $this->parameters[$name] : null; } /** * Checks if a parameter value is set for the given parameter. * * @param string $name A parameter name * * @return Boolean true if the parameter value is set, false otherwise */ public function hasParameter($name) { return array_key_exists($name, $this->parameters); } /** * Sets a parameter value. * * @param string $name A parameter name * @param mixed $parameter The parameter value * * @api */ public function setParameter($name, $parameter) { $this->parameters[$name] = $parameter; } } PK]pBQ Q !Routing/Loader/YamlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\Config\Loader\FileLoader; /** * YamlFileLoader loads Yaml routing files. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class YamlFileLoader extends FileLoader { private static $availableKeys = array( 'resource', 'type', 'prefix', 'pattern', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition' ); private $yamlParser; /** * Loads a Yaml file. * * @param string $file A Yaml file path * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @throws \InvalidArgumentException When a route can't be parsed because YAML is invalid * * @api */ public function load($file, $type = null) { $path = $this->locator->locate($file); if (!stream_is_local($path)) { throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path)); } if (!file_exists($path)) { throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path)); } if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } $config = $this->yamlParser->parse(file_get_contents($path)); $collection = new RouteCollection(); $collection->addResource(new FileResource($path)); // empty file if (null === $config) { return $collection; } // not an array if (!is_array($config)) { throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path)); } foreach ($config as $name => $config) { if (isset($config['pattern'])) { if (isset($config['path'])) { throw new \InvalidArgumentException(sprintf('The file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path)); } $config['path'] = $config['pattern']; unset($config['pattern']); } $this->validate($config, $name, $path); if (isset($config['resource'])) { $this->parseImport($collection, $config, $path, $file); } else { $this->parseRoute($collection, $name, $config, $path); } } return $collection; } /** * {@inheritdoc} * * @api */ public function supports($resource, $type = null) { return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'yaml' === $type); } /** * Parses a route and adds it to the RouteCollection. * * @param RouteCollection $collection A RouteCollection instance * @param string $name Route name * @param array $config Route definition * @param string $path Full path of the YAML file being processed */ protected function parseRoute(RouteCollection $collection, $name, array $config, $path) { $defaults = isset($config['defaults']) ? $config['defaults'] : array(); $requirements = isset($config['requirements']) ? $config['requirements'] : array(); $options = isset($config['options']) ? $config['options'] : array(); $host = isset($config['host']) ? $config['host'] : ''; $schemes = isset($config['schemes']) ? $config['schemes'] : array(); $methods = isset($config['methods']) ? $config['methods'] : array(); $condition = isset($config['condition']) ? $config['condition'] : null; $route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition); $collection->add($name, $route); } /** * Parses an import and adds the routes in the resource to the RouteCollection. * * @param RouteCollection $collection A RouteCollection instance * @param array $config Route definition * @param string $path Full path of the YAML file being processed * @param string $file Loaded file name */ protected function parseImport(RouteCollection $collection, array $config, $path, $file) { $type = isset($config['type']) ? $config['type'] : null; $prefix = isset($config['prefix']) ? $config['prefix'] : ''; $defaults = isset($config['defaults']) ? $config['defaults'] : array(); $requirements = isset($config['requirements']) ? $config['requirements'] : array(); $options = isset($config['options']) ? $config['options'] : array(); $host = isset($config['host']) ? $config['host'] : null; $condition = isset($config['condition']) ? $config['condition'] : null; $schemes = isset($config['schemes']) ? $config['schemes'] : null; $methods = isset($config['methods']) ? $config['methods'] : null; $this->setCurrentDir(dirname($path)); $subCollection = $this->import($config['resource'], $type, false, $file); /* @var $subCollection RouteCollection */ $subCollection->addPrefix($prefix); if (null !== $host) { $subCollection->setHost($host); } if (null !== $condition) { $subCollection->setCondition($condition); } if (null !== $schemes) { $subCollection->setSchemes($schemes); } if (null !== $methods) { $subCollection->setMethods($methods); } $subCollection->addDefaults($defaults); $subCollection->addRequirements($requirements); $subCollection->addOptions($options); $collection->addCollection($subCollection); } /** * Validates the route configuration. * * @param array $config A resource config * @param string $name The config key * @param string $path The loaded file path * * @throws \InvalidArgumentException If one of the provided config keys is not supported, * something is missing or the combination is nonsense */ protected function validate($config, $name, $path) { if (!is_array($config)) { throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path)); } if ($extraKeys = array_diff(array_keys($config), self::$availableKeys)) { throw new \InvalidArgumentException(sprintf( 'The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys) )); } if (isset($config['resource']) && isset($config['path'])) { throw new \InvalidArgumentException(sprintf( 'The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name )); } if (!isset($config['resource']) && isset($config['type'])) { throw new \InvalidArgumentException(sprintf( 'The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path )); } if (!isset($config['resource']) && !isset($config['path'])) { throw new \InvalidArgumentException(sprintf( 'You must define a "path" for the route "%s" in file "%s".', $name, $path )); } } } PK]?-[ -Routing/Loader/schema/routing/routing-1.0.xsdnu[ PK]nhh Routing/Loader/ClosureLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\Loader; use Symfony\Component\Routing\RouteCollection; /** * ClosureLoader loads routes from a PHP closure. * * The Closure must return a RouteCollection instance. * * @author Fabien Potencier * * @api */ class ClosureLoader extends Loader { /** * Loads a Closure. * * @param \Closure $closure A Closure * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @api */ public function load($closure, $type = null) { return call_user_func($closure); } /** * {@inheritdoc} * * @api */ public function supports($resource, $type = null) { return $resource instanceof \Closure && (!$type || 'closure' === $type); } } PK]? ,Routing/Loader/AnnotationDirectoryLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Config\Resource\DirectoryResource; /** * AnnotationDirectoryLoader loads routing information from annotations set * on PHP classes and methods. * * @author Fabien Potencier */ class AnnotationDirectoryLoader extends AnnotationFileLoader { /** * Loads from annotations from a directory. * * @param string $path A directory path * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed */ public function load($path, $type = null) { $dir = $this->locator->locate($path); $collection = new RouteCollection(); $collection->addResource(new DirectoryResource($dir, '/\.php$/')); $files = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY)); usort($files, function (\SplFileInfo $a, \SplFileInfo $b) { return (string) $a > (string) $b ? 1 : -1; }); foreach ($files as $file) { if (!$file->isFile() || '.php' !== substr($file->getFilename(), -4)) { continue; } if ($class = $this->findClass($file)) { $refl = new \ReflectionClass($class); if ($refl->isAbstract()) { continue; } $collection->addCollection($this->loader->load($class, $type)); } } return $collection; } /** * {@inheritdoc} */ public function supports($resource, $type = null) { try { $path = $this->locator->locate($resource); } catch (\Exception $e) { return false; } return is_string($resource) && is_dir($path) && (!$type || 'annotation' === $type); } } PK]~LW(Routing/Loader/AnnotationClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Doctrine\Common\Annotations\Reader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Loader\LoaderResolverInterface; /** * AnnotationClassLoader loads routing information from a PHP class and its methods. * * You need to define an implementation for the getRouteDefaults() method. Most of the * time, this method should define some PHP callable to be called for the route * (a controller in MVC speak). * * The @Route annotation can be set on the class (for global parameters), * and on each method. * * The @Route annotation main value is the route path. The annotation also * recognizes several parameters: requirements, options, defaults, schemes, * methods, host, and name. The name parameter is mandatory. * Here is an example of how you should be able to use it: * * /** * * @Route("/Blog") * * / * class Blog * { * /** * * @Route("/", name="blog_index") * * / * public function index() * { * } * * /** * * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"}) * * / * public function show() * { * } * } * * @author Fabien Potencier */ abstract class AnnotationClassLoader implements LoaderInterface { /** * @var Reader */ protected $reader; /** * @var string */ protected $routeAnnotationClass = 'Symfony\\Component\\Routing\\Annotation\\Route'; /** * @var integer */ protected $defaultRouteIndex = 0; /** * Constructor. * * @param Reader $reader */ public function __construct(Reader $reader) { $this->reader = $reader; } /** * Sets the annotation class to read route properties from. * * @param string $class A fully-qualified class name */ public function setRouteAnnotationClass($class) { $this->routeAnnotationClass = $class; } /** * Loads from annotations from a class. * * @param string $class A class name * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @throws \InvalidArgumentException When route can't be parsed */ public function load($class, $type = null) { if (!class_exists($class)) { throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); } $globals = array( 'path' => '', 'requirements' => array(), 'options' => array(), 'defaults' => array(), 'schemes' => array(), 'methods' => array(), 'host' => '', 'condition' => '', ); $class = new \ReflectionClass($class); if ($class->isAbstract()) { throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class)); } if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { // for BC reasons if (null !== $annot->getPath()) { $globals['path'] = $annot->getPath(); } elseif (null !== $annot->getPattern()) { $globals['path'] = $annot->getPattern(); } if (null !== $annot->getRequirements()) { $globals['requirements'] = $annot->getRequirements(); } if (null !== $annot->getOptions()) { $globals['options'] = $annot->getOptions(); } if (null !== $annot->getDefaults()) { $globals['defaults'] = $annot->getDefaults(); } if (null !== $annot->getSchemes()) { $globals['schemes'] = $annot->getSchemes(); } if (null !== $annot->getMethods()) { $globals['methods'] = $annot->getMethods(); } if (null !== $annot->getHost()) { $globals['host'] = $annot->getHost(); } if (null !== $annot->getCondition()) { $globals['condition'] = $annot->getCondition(); } } $collection = new RouteCollection(); $collection->addResource(new FileResource($class->getFileName())); foreach ($class->getMethods() as $method) { $this->defaultRouteIndex = 0; foreach ($this->reader->getMethodAnnotations($method) as $annot) { if ($annot instanceof $this->routeAnnotationClass) { $this->addRoute($collection, $annot, $globals, $class, $method); } } } return $collection; } protected function addRoute(RouteCollection $collection, $annot, $globals, \ReflectionClass $class, \ReflectionMethod $method) { $name = $annot->getName(); if (null === $name) { $name = $this->getDefaultRouteName($class, $method); } $defaults = array_replace($globals['defaults'], $annot->getDefaults()); foreach ($method->getParameters() as $param) { if (!isset($defaults[$param->getName()]) && $param->isOptional()) { $defaults[$param->getName()] = $param->getDefaultValue(); } } $requirements = array_replace($globals['requirements'], $annot->getRequirements()); $options = array_replace($globals['options'], $annot->getOptions()); $schemes = array_replace($globals['schemes'], $annot->getSchemes()); $methods = array_replace($globals['methods'], $annot->getMethods()); $host = $annot->getHost(); if (null === $host) { $host = $globals['host']; } $condition = $annot->getCondition(); if (null === $condition) { $condition = $globals['condition']; } $route = new Route($globals['path'].$annot->getPath(), $defaults, $requirements, $options, $host, $schemes, $methods, $condition); $this->configureRoute($route, $class, $method, $annot); $collection->add($name, $route); } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); } /** * {@inheritdoc} */ public function setResolver(LoaderResolverInterface $resolver) { } /** * {@inheritdoc} */ public function getResolver() { } /** * Gets the default route name for a class method. * * @param \ReflectionClass $class * @param \ReflectionMethod $method * * @return string */ protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) { $name = strtolower(str_replace('\\', '_', $class->name).'_'.$method->name); if ($this->defaultRouteIndex > 0) { $name .= '_'.$this->defaultRouteIndex; } $this->defaultRouteIndex++; return $name; } abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot); } PK]أ2D$D$ Routing/Loader/XmlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Util\XmlUtils; /** * XmlFileLoader loads XML routing files. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class XmlFileLoader extends FileLoader { const NAMESPACE_URI = 'http://symfony.com/schema/routing'; const SCHEME_PATH = '/schema/routing/routing-1.0.xsd'; /** * Loads an XML file. * * @param string $file An XML file path * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @throws \InvalidArgumentException When the file cannot be loaded or when the XML cannot be * parsed because it does not validate against the scheme. * * @api */ public function load($file, $type = null) { $path = $this->locator->locate($file); $xml = $this->loadFile($path); $collection = new RouteCollection(); $collection->addResource(new FileResource($path)); // process routes and imports foreach ($xml->documentElement->childNodes as $node) { if (!$node instanceof \DOMElement) { continue; } $this->parseNode($collection, $node, $path, $file); } return $collection; } /** * Parses a node from a loaded XML file. * * @param RouteCollection $collection Collection to associate with the node * @param \DOMElement $node Element to parse * @param string $path Full path of the XML file being processed * @param string $file Loaded file name * * @throws \InvalidArgumentException When the XML is invalid */ protected function parseNode(RouteCollection $collection, \DOMElement $node, $path, $file) { if (self::NAMESPACE_URI !== $node->namespaceURI) { return; } switch ($node->localName) { case 'route': $this->parseRoute($collection, $node, $path); break; case 'import': $this->parseImport($collection, $node, $path, $file); break; default: throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path)); } } /** * {@inheritdoc} * * @api */ public function supports($resource, $type = null) { return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'xml' === $type); } /** * Parses a route and adds it to the RouteCollection. * * @param RouteCollection $collection RouteCollection instance * @param \DOMElement $node Element to parse that represents a Route * @param string $path Full path of the XML file being processed * * @throws \InvalidArgumentException When the XML is invalid */ protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path) { if ('' === ($id = $node->getAttribute('id')) || (!$node->hasAttribute('pattern') && !$node->hasAttribute('path'))) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must have an "id" and a "path" attribute.', $path)); } if ($node->hasAttribute('pattern')) { if ($node->hasAttribute('path')) { throw new \InvalidArgumentException(sprintf('The element in file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path)); } $node->setAttribute('path', $node->getAttribute('pattern')); $node->removeAttribute('pattern'); } $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY); $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY); list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path); $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition); $collection->add($id, $route); } /** * Parses an import and adds the routes in the resource to the RouteCollection. * * @param RouteCollection $collection RouteCollection instance * @param \DOMElement $node Element to parse that represents a Route * @param string $path Full path of the XML file being processed * @param string $file Loaded file name * * @throws \InvalidArgumentException When the XML is invalid */ protected function parseImport(RouteCollection $collection, \DOMElement $node, $path, $file) { if ('' === $resource = $node->getAttribute('resource')) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "resource" attribute.', $path)); } $type = $node->getAttribute('type'); $prefix = $node->getAttribute('prefix'); $host = $node->hasAttribute('host') ? $node->getAttribute('host') : null; $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null; $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null; list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path); $this->setCurrentDir(dirname($path)); $subCollection = $this->import($resource, ('' !== $type ? $type : null), false, $file); /* @var $subCollection RouteCollection */ $subCollection->addPrefix($prefix); if (null !== $host) { $subCollection->setHost($host); } if (null !== $condition) { $subCollection->setCondition($condition); } if (null !== $schemes) { $subCollection->setSchemes($schemes); } if (null !== $methods) { $subCollection->setMethods($methods); } $subCollection->addDefaults($defaults); $subCollection->addRequirements($requirements); $subCollection->addOptions($options); $collection->addCollection($subCollection); } /** * Loads an XML file. * * @param string $file An XML file path * * @return \DOMDocument * * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors * or when the XML structure is not as expected by the scheme - * see validate() */ protected function loadFile($file) { return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH); } /** * Parses the config elements (default, requirement, option). * * @param \DOMElement $node Element to parse that contains the configs * @param string $path Full path of the XML file being processed * * @return array An array with the defaults as first item, requirements as second and options as third. * * @throws \InvalidArgumentException When the XML is invalid */ private function parseConfigs(\DOMElement $node, $path) { $defaults = array(); $requirements = array(); $options = array(); $condition = null; foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) { switch ($n->localName) { case 'default': if ($n->hasAttribute('xsi:nil') && 'true' == $n->getAttribute('xsi:nil')) { $defaults[$n->getAttribute('key')] = null; } else { $defaults[$n->getAttribute('key')] = trim($n->textContent); } break; case 'requirement': $requirements[$n->getAttribute('key')] = trim($n->textContent); break; case 'option': $options[$n->getAttribute('key')] = trim($n->textContent); break; case 'condition': $condition = trim($n->textContent); break; default: throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement" or "option".', $n->localName, $path)); } } return array($defaults, $requirements, $options, $condition); } } PK]Pi{ Routing/Loader/PhpFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\RouteCollection; /** * PhpFileLoader loads routes from a PHP file. * * The file must return a RouteCollection instance. * * @author Fabien Potencier * * @api */ class PhpFileLoader extends FileLoader { /** * Loads a PHP file. * * @param string $file A PHP file path * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @api */ public function load($file, $type = null) { // the loader variable is exposed to the included file below $loader = $this; $path = $this->locator->locate($file); $this->setCurrentDir(dirname($path)); $collection = include $path; $collection->addResource(new FileResource($path)); return $collection; } /** * {@inheritdoc} * * @api */ public function supports($resource, $type = null) { return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'php' === $type); } } PK]~ޟ 'Routing/Loader/AnnotationFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\FileLocatorInterface; /** * AnnotationFileLoader loads routing information from annotations set * on a PHP class and its methods. * * @author Fabien Potencier */ class AnnotationFileLoader extends FileLoader { protected $loader; /** * Constructor. * * @param FileLocatorInterface $locator A FileLocator instance * @param AnnotationClassLoader $loader An AnnotationClassLoader instance * * @throws \RuntimeException */ public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader) { if (!function_exists('token_get_all')) { throw new \RuntimeException('The Tokenizer extension is required for the routing annotation loaders.'); } parent::__construct($locator); $this->loader = $loader; } /** * Loads from annotations from a file. * * @param string $file A PHP file path * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed */ public function load($file, $type = null) { $path = $this->locator->locate($file); $collection = new RouteCollection(); if ($class = $this->findClass($path)) { $collection->addResource(new FileResource($path)); $collection->addCollection($this->loader->load($class, $type)); } return $collection; } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type); } /** * Returns the full class name for the first class in the file. * * @param string $file A PHP file path * * @return string|false Full class name if found, false otherwise */ protected function findClass($file) { $class = false; $namespace = false; $tokens = token_get_all(file_get_contents($file)); for ($i = 0, $count = count($tokens); $i < $count; $i++) { $token = $tokens[$i]; if (!is_array($token)) { continue; } if (true === $class && T_STRING === $token[0]) { return $namespace.'\\'.$token[1]; } if (true === $namespace && T_STRING === $token[0]) { $namespace = ''; do { $namespace .= $token[1]; $token = $tokens[++$i]; } while ($i < $count && is_array($token) && in_array($token[0], array(T_NS_SEPARATOR, T_STRING))); } if (T_CLASS === $token[0]) { $class = true; } if (T_NAMESPACE === $token[0]) { $namespace = true; } } return false; } } PK]V˽ Routing/Annotation/Route.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Annotation; /** * Annotation class for @Route(). * * @Annotation * * @author Fabien Potencier */ class Route { private $path; private $name; private $requirements = array(); private $options = array(); private $defaults = array(); private $host; private $methods = array(); private $schemes = array(); private $condition; /** * Constructor. * * @param array $data An array of key/value parameters. * * @throws \BadMethodCallException */ public function __construct(array $data) { if (isset($data['value'])) { $data['path'] = $data['value']; unset($data['value']); } foreach ($data as $key => $value) { $method = 'set'.str_replace('_', '', $key); if (!method_exists($this, $method)) { throw new \BadMethodCallException(sprintf("Unknown property '%s' on annotation '%s'.", $key, get_class($this))); } $this->$method($value); } } /** * @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead. */ public function setPattern($pattern) { $this->path = $pattern; } /** * @deprecated Deprecated in 2.2, to be removed in 3.0. Use getPath instead. */ public function getPattern() { return $this->path; } public function setPath($path) { $this->path = $path; } public function getPath() { return $this->path; } public function setHost($pattern) { $this->host = $pattern; } public function getHost() { return $this->host; } public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } public function setRequirements($requirements) { $this->requirements = $requirements; } public function getRequirements() { return $this->requirements; } public function setOptions($options) { $this->options = $options; } public function getOptions() { return $this->options; } public function setDefaults($defaults) { $this->defaults = $defaults; } public function getDefaults() { return $this->defaults; } public function setSchemes($schemes) { $this->schemes = is_array($schemes) ? $schemes : array($schemes); } public function getSchemes() { return $this->schemes; } public function setMethods($methods) { $this->methods = is_array($methods) ? $methods : array($methods); } public function getMethods() { return $this->methods; } public function setCondition($condition) { $this->condition = $condition; } public function getCondition() { return $this->condition; } } PK])(Routing/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * ExceptionInterface * * @author Alexandre Salomé * * @api */ interface ExceptionInterface { } PK]j`j/Routing/Exception/InvalidParameterException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * Exception thrown when a parameter is not valid * * @author Alexandre Salomé * * @api */ class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface { } PK]njW,Routing/Exception/RouteNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * Exception thrown when a route does not exist * * @author Alexandre Salomé * * @api */ class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface { } PK]==9Routing/Exception/MissingMandatoryParametersException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * Exception thrown when a route cannot be generated because of missing * mandatory parameters. * * @author Alexandre Salomé * * @api */ class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface { } PK]JJ/Routing/Exception/MethodNotAllowedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * The resource was found but the request method is not allowed. * * This exception should trigger an HTTP 405 response in your application code. * * @author Kris Wallsmith * * @api */ class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface { /** * @var array */ protected $allowedMethods = array(); public function __construct(array $allowedMethods, $message = null, $code = 0, \Exception $previous = null) { $this->allowedMethods = array_map('strtoupper', $allowedMethods); parent::__construct($message, $code, $previous); } /** * Gets the allowed HTTP methods. * * @return array */ public function getAllowedMethods() { return $this->allowedMethods; } } PK]?]///Routing/Exception/ResourceNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * The resource was not found. * * This exception should trigger an HTTP 404 response in your application code. * * @author Kris Wallsmith * * @api */ class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface { } PK]U8Routing/RouterInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; /** * RouterInterface is the interface that all Router classes must implement. * * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface. * * @author Fabien Potencier */ interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface { /** * Gets the RouteCollection instance associated with this Router. * * @return RouteCollection A RouteCollection instance */ public function getRouteCollection(); } PK]r(Routing/RequestContextAwareInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * @api */ interface RequestContextAwareInterface { /** * Sets the request context. * * @param RequestContext $context The context * * @api */ public function setContext(RequestContext $context); /** * Gets the request context. * * @return RequestContext The context * * @api */ public function getContext(); } PK]45Routing/Generator/Dumper/GeneratorDumperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator\Dumper; use Symfony\Component\Routing\RouteCollection; /** * GeneratorDumperInterface is the interface that all generator dumper classes must implement. * * @author Fabien Potencier * * @api */ interface GeneratorDumperInterface { /** * Dumps a set of routes to a string representation of executable code * that can then be used to generate a URL of such a route. * * @param array $options An array of options * * @return string Executable code */ public function dump(array $options = array()); /** * Gets the routes to dump. * * @return RouteCollection A RouteCollection instance */ public function getRoutes(); } PK]u ',Routing/Generator/Dumper/GeneratorDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator\Dumper; use Symfony\Component\Routing\RouteCollection; /** * GeneratorDumper is the base class for all built-in generator dumpers. * * @author Fabien Potencier */ abstract class GeneratorDumper implements GeneratorDumperInterface { /** * @var RouteCollection */ private $routes; /** * Constructor. * * @param RouteCollection $routes The RouteCollection to dump */ public function __construct(RouteCollection $routes) { $this->routes = $routes; } /** * {@inheritdoc} */ public function getRoutes() { return $this->routes; } } PK]1O /Routing/Generator/Dumper/PhpGeneratorDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator\Dumper; /** * PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class PhpGeneratorDumper extends GeneratorDumper { /** * Dumps a set of routes to a PHP class. * * Available options: * * * class: The class name * * base_class: The base class name * * @param array $options An array of options * * @return string A PHP class representing the generator class * * @api */ public function dump(array $options = array()) { $options = array_merge(array( 'class' => 'ProjectUrlGenerator', 'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', ), $options); return <<generateDeclaredRoutes()}; /** * Constructor. */ public function __construct(RequestContext \$context, LoggerInterface \$logger = null) { \$this->context = \$context; \$this->logger = \$logger; } {$this->generateGenerateMethod()} } EOF; } /** * Generates PHP code representing an array of defined routes * together with the routes properties (e.g. requirements). * * @return string PHP code */ private function generateDeclaredRoutes() { $routes = "array(\n"; foreach ($this->getRoutes()->all() as $name => $route) { $compiledRoute = $route->compile(); $properties = array(); $properties[] = $compiledRoute->getVariables(); $properties[] = $route->getDefaults(); $properties[] = $route->getRequirements(); $properties[] = $compiledRoute->getTokens(); $properties[] = $compiledRoute->getHostTokens(); $routes .= sprintf(" '%s' => %s,\n", $name, str_replace("\n", '', var_export($properties, true))); } $routes .= ' )'; return $routes; } /** * Generates PHP code representing the `generate` method that implements the UrlGeneratorInterface. * * @return string PHP code */ private function generateGenerateMethod() { return <<doGenerate(\$variables, \$defaults, \$requirements, \$tokens, \$parameters, \$name, \$referenceType, \$hostTokens); } EOF; } } PK] 11"Routing/Generator/UrlGenerator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Exception\InvalidParameterException; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; use Psr\Log\LoggerInterface; /** * UrlGenerator can generate a URL or a path for any route in the RouteCollection * based on the passed parameters. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface { /** * @var RouteCollection */ protected $routes; /** * @var RequestContext */ protected $context; /** * @var Boolean|null */ protected $strictRequirements = true; /** * @var LoggerInterface|null */ protected $logger; /** * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL. * * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g. * "?" and "#" (would be interpreted wrongly as query and fragment identifier), * "'" and """ (are used as delimiters in HTML). */ protected $decodedChars = array( // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning // some webservers don't allow the slash in encoded form in the path for security reasons anyway // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss '%2F' => '/', // the following chars are general delimiters in the URI specification but have only special meaning in the authority component // so they can safely be used in the path in unencoded form '%40' => '@', '%3A' => ':', // these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally // so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability '%3B' => ';', '%2C' => ',', '%3D' => '=', '%2B' => '+', '%21' => '!', '%2A' => '*', '%7C' => '|', ); /** * Constructor. * * @param RouteCollection $routes A RouteCollection instance * @param RequestContext $context The context * @param LoggerInterface|null $logger A logger instance * * @api */ public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null) { $this->routes = $routes; $this->context = $context; $this->logger = $logger; } /** * {@inheritdoc} */ public function setContext(RequestContext $context) { $this->context = $context; } /** * {@inheritdoc} */ public function getContext() { return $this->context; } /** * {@inheritdoc} */ public function setStrictRequirements($enabled) { $this->strictRequirements = null === $enabled ? null : (Boolean) $enabled; } /** * {@inheritdoc} */ public function isStrictRequirements() { return $this->strictRequirements; } /** * {@inheritDoc} */ public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) { if (null === $route = $this->routes->get($name)) { throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); } // the Route has a cache of its own and is not recompiled as long as it does not get modified $compiledRoute = $route->compile(); return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens()); } /** * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route * @throws InvalidParameterException When a parameter value for a placeholder is not correct because * it does not match the requirement */ protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens) { $variables = array_flip($variables); $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); // all params must be given if ($diff = array_diff_key($variables, $mergedParams)) { throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name)); } $url = ''; $optional = true; foreach ($tokens as $token) { if ('variable' === $token[0]) { if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) { // check requirement if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) { $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]); if ($this->strictRequirements) { throw new InvalidParameterException($message); } if ($this->logger) { $this->logger->error($message); } return null; } $url = $token[1].$mergedParams[$token[3]].$url; $optional = false; } } else { // static text $url = $token[1].$url; $optional = false; } } if ('' === $url) { $url = '/'; } // the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request) $url = strtr(rawurlencode($url), $this->decodedChars); // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 // so we need to encode them as they are not used for this purpose here // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route $url = strtr($url, array('/../' => '/%2E%2E/', '/./' => '/%2E/')); if ('/..' === substr($url, -3)) { $url = substr($url, 0, -2).'%2E%2E'; } elseif ('/.' === substr($url, -2)) { $url = substr($url, 0, -1).'%2E'; } $schemeAuthority = ''; if ($host = $this->context->getHost()) { $scheme = $this->context->getScheme(); if (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme !== $req) { $referenceType = self::ABSOLUTE_URL; $scheme = $req; } if ($hostTokens) { $routeHost = ''; foreach ($hostTokens as $token) { if ('variable' === $token[0]) { if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) { $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]); if ($this->strictRequirements) { throw new InvalidParameterException($message); } if ($this->logger) { $this->logger->error($message); } return null; } $routeHost = $token[1].$mergedParams[$token[3]].$routeHost; } else { $routeHost = $token[1].$routeHost; } } if ($routeHost !== $host) { $host = $routeHost; if (self::ABSOLUTE_URL !== $referenceType) { $referenceType = self::NETWORK_PATH; } } } if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) { $port = ''; if ('http' === $scheme && 80 != $this->context->getHttpPort()) { $port = ':'.$this->context->getHttpPort(); } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { $port = ':'.$this->context->getHttpsPort(); } $schemeAuthority = self::NETWORK_PATH === $referenceType ? '//' : "$scheme://"; $schemeAuthority .= $host.$port; } } if (self::RELATIVE_PATH === $referenceType) { $url = self::getRelativePath($this->context->getPathInfo(), $url); } else { $url = $schemeAuthority.$this->context->getBaseUrl().$url; } // add a query string if needed $extra = array_diff_key($parameters, $variables, $defaults); if ($extra && $query = http_build_query($extra, '', '&')) { $url .= '?'.$query; } return $url; } /** * Returns the target path as relative reference from the base path. * * Only the URIs path component (no schema, host etc.) is relevant and must be given, starting with a slash. * Both paths must be absolute and not contain relative parts. * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. * Furthermore, they can be used to reduce the link size in documents. * * Example target paths, given a base path of "/a/b/c/d": * - "/a/b/c/d" -> "" * - "/a/b/c/" -> "./" * - "/a/b/" -> "../" * - "/a/b/c/other" -> "other" * - "/a/x/y" -> "../../x/y" * * @param string $basePath The base path * @param string $targetPath The target path * * @return string The relative target path */ public static function getRelativePath($basePath, $targetPath) { if ($basePath === $targetPath) { return ''; } $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); $targetDirs = explode('/', isset($targetPath[0]) && '/' === $targetPath[0] ? substr($targetPath, 1) : $targetPath); array_pop($sourceDirs); $targetFile = array_pop($targetDirs); foreach ($sourceDirs as $i => $dir) { if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { unset($sourceDirs[$i], $targetDirs[$i]); } else { break; } } $targetDirs[] = $targetFile; $path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs); // A reference to the same base directory or an empty subdirectory must be prefixed with "./". // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used // as the first segment of a relative-path reference, as it would be mistaken for a scheme name // (see http://tools.ietf.org/html/rfc3986#section-4.2). return '' === $path || '/' === $path[0] || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) ? "./$path" : $path; } } PK]մ7Routing/Generator/ConfigurableRequirementsInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator; /** * ConfigurableRequirementsInterface must be implemented by URL generators that * can be configured whether an exception should be generated when the parameters * do not match the requirements. It is also possible to disable the requirements * check for URL generation completely. * * The possible configurations and use-cases: * - setStrictRequirements(true): Throw an exception for mismatching requirements. This * is mostly useful in development environment. * - setStrictRequirements(false): Don't throw an exception but return null as URL for * mismatching requirements and log the problem. Useful when you cannot control all * params because they come from third party libs but don't want to have a 404 in * production environment. It should log the mismatch so one can review it. * - setStrictRequirements(null): Return the URL with the given parameters without * checking the requirements at all. When generating a URL you should either trust * your params or you validated them beforehand because otherwise it would break your * link anyway. So in production environment you should know that params always pass * the requirements. Thus this option allows to disable the check on URL generation for * performance reasons (saving a preg_match for each requirement every time a URL is * generated). * * @author Fabien Potencier * @author Tobias Schultze */ interface ConfigurableRequirementsInterface { /** * Enables or disables the exception on incorrect parameters. * Passing null will deactivate the requirements check completely. * * @param Boolean|null $enabled */ public function setStrictRequirements($enabled); /** * Returns whether to throw an exception on incorrect parameters. * Null means the requirements check is deactivated completely. * * @return Boolean|null */ public function isStrictRequirements(); } PK]@@+Routing/Generator/UrlGeneratorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator; use Symfony\Component\Routing\Exception\InvalidParameterException; use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\RequestContextAwareInterface; /** * UrlGeneratorInterface is the interface that all URL generator classes must implement. * * The constants in this interface define the different types of resource references that * are declared in RFC 3986: http://tools.ietf.org/html/rfc3986 * We are using the term "URL" instead of "URI" as this is more common in web applications * and we do not need to distinguish them as the difference is mostly semantical and * less technical. Generating URIs, i.e. representation-independent resource identifiers, * is also possible. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ interface UrlGeneratorInterface extends RequestContextAwareInterface { /** * Generates an absolute URL, e.g. "http://example.com/dir/file". */ const ABSOLUTE_URL = true; /** * Generates an absolute path, e.g. "/dir/file". */ const ABSOLUTE_PATH = false; /** * Generates a relative path based on the current request path, e.g. "../parent-file". * @see UrlGenerator::getRelativePath() */ const RELATIVE_PATH = 'relative'; /** * Generates a network path, e.g. "//example.com/dir/file". * Such reference reuses the current scheme but specifies the host. */ const NETWORK_PATH = 'network'; /** * Generates a URL or path for a specific route based on the given parameters. * * Parameters that reference placeholders in the route pattern will substitute them in the * path or host. Extra params are added as query string to the URL. * * When the passed reference type cannot be generated for the route because it requires a different * host or scheme than the current one, the method will return a more comprehensive reference * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH * but the route requires the https scheme whereas the current scheme is http, it will instead return an * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches * the route in any case. * * If there is no route with the given name, the generator must throw the RouteNotFoundException. * * @param string $name The name of the route * @param mixed $parameters An array of parameters * @param Boolean|string $referenceType The type of reference to be generated (one of the constants) * * @return string The generated URL * * @throws RouteNotFoundException If the named route doesn't exist * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route * @throws InvalidParameterException When a parameter value for a placeholder is not correct because * it does not match the requirement * * @api */ public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH); } PK] %%Routing/Router.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\ConfigCache; use Psr\Log\LoggerInterface; use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface; use Symfony\Component\HttpFoundation\Request; /** * The Router class is an example of the integration of all pieces of the * routing system for easier use. * * @author Fabien Potencier */ class Router implements RouterInterface, RequestMatcherInterface { /** * @var UrlMatcherInterface|null */ protected $matcher; /** * @var UrlGeneratorInterface|null */ protected $generator; /** * @var RequestContext */ protected $context; /** * @var LoaderInterface */ protected $loader; /** * @var RouteCollection|null */ protected $collection; /** * @var mixed */ protected $resource; /** * @var array */ protected $options = array(); /** * @var LoggerInterface|null */ protected $logger; /** * Constructor. * * @param LoaderInterface $loader A LoaderInterface instance * @param mixed $resource The main resource to load * @param array $options An array of options * @param RequestContext $context The context * @param LoggerInterface $logger A logger instance */ public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, LoggerInterface $logger = null) { $this->loader = $loader; $this->resource = $resource; $this->logger = $logger; $this->context = $context ?: new RequestContext(); $this->setOptions($options); } /** * Sets options. * * Available options: * * * cache_dir: The cache directory (or null to disable caching) * * debug: Whether to enable debugging or not (false by default) * * resource_type: Type hint for the main resource (optional) * * @param array $options An array of options * * @throws \InvalidArgumentException When unsupported option is provided */ public function setOptions(array $options) { $this->options = array( 'cache_dir' => null, 'debug' => false, 'generator_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', 'generator_base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', 'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper', 'generator_cache_class' => 'ProjectUrlGenerator', 'matcher_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', 'matcher_base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', 'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper', 'matcher_cache_class' => 'ProjectUrlMatcher', 'resource_type' => null, 'strict_requirements' => true, ); // check option names and live merge, if errors are encountered Exception will be thrown $invalid = array(); foreach ($options as $key => $value) { if (array_key_exists($key, $this->options)) { $this->options[$key] = $value; } else { $invalid[] = $key; } } if ($invalid) { throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid))); } } /** * Sets an option. * * @param string $key The key * @param mixed $value The value * * @throws \InvalidArgumentException */ public function setOption($key, $value) { if (!array_key_exists($key, $this->options)) { throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); } $this->options[$key] = $value; } /** * Gets an option value. * * @param string $key The key * * @return mixed The value * * @throws \InvalidArgumentException */ public function getOption($key) { if (!array_key_exists($key, $this->options)) { throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); } return $this->options[$key]; } /** * {@inheritdoc} */ public function getRouteCollection() { if (null === $this->collection) { $this->collection = $this->loader->load($this->resource, $this->options['resource_type']); } return $this->collection; } /** * {@inheritdoc} */ public function setContext(RequestContext $context) { $this->context = $context; if (null !== $this->matcher) { $this->getMatcher()->setContext($context); } if (null !== $this->generator) { $this->getGenerator()->setContext($context); } } /** * {@inheritdoc} */ public function getContext() { return $this->context; } /** * {@inheritdoc} */ public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) { return $this->getGenerator()->generate($name, $parameters, $referenceType); } /** * {@inheritdoc} */ public function match($pathinfo) { return $this->getMatcher()->match($pathinfo); } /** * {@inheritdoc} */ public function matchRequest(Request $request) { $matcher = $this->getMatcher(); if (!$matcher instanceof RequestMatcherInterface) { // fallback to the default UrlMatcherInterface return $matcher->match($request->getPathInfo()); } return $matcher->matchRequest($request); } /** * Gets the UrlMatcher instance associated with this Router. * * @return UrlMatcherInterface A UrlMatcherInterface instance */ public function getMatcher() { if (null !== $this->matcher) { return $this->matcher; } if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) { return $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context); } $class = $this->options['matcher_cache_class']; $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); if (!$cache->isFresh()) { $dumper = $this->getMatcherDumperInstance(); $options = array( 'class' => $class, 'base_class' => $this->options['matcher_base_class'], ); $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); } require_once $cache; return $this->matcher = new $class($this->context); } /** * Gets the UrlGenerator instance associated with this Router. * * @return UrlGeneratorInterface A UrlGeneratorInterface instance */ public function getGenerator() { if (null !== $this->generator) { return $this->generator; } if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) { $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger); } else { $class = $this->options['generator_cache_class']; $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); if (!$cache->isFresh()) { $dumper = $this->getGeneratorDumperInstance(); $options = array( 'class' => $class, 'base_class' => $this->options['generator_base_class'], ); $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); } require_once $cache; $this->generator = new $class($this->context, $this->logger); } if ($this->generator instanceof ConfigurableRequirementsInterface) { $this->generator->setStrictRequirements($this->options['strict_requirements']); } return $this->generator; } /** * @return GeneratorDumperInterface */ protected function getGeneratorDumperInstance() { return new $this->options['generator_dumper_class']($this->getRouteCollection()); } /** * @return MatcherDumperInterface */ protected function getMatcherDumperInstance() { return new $this->options['matcher_dumper_class']($this->getRouteCollection()); } } PK]UcQQRouting/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\Config\Resource\ResourceInterface; /** * A RouteCollection represents a set of Route instances. * * When adding a route at the end of the collection, an existing route * with the same name is removed first. So there can only be one route * with a given name. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class RouteCollection implements \IteratorAggregate, \Countable { /** * @var Route[] */ private $routes = array(); /** * @var array */ private $resources = array(); public function __clone() { foreach ($this->routes as $name => $route) { $this->routes[$name] = clone $route; } } /** * Gets the current RouteCollection as an Iterator that includes all routes. * * It implements \IteratorAggregate. * * @see all() * * @return \ArrayIterator An \ArrayIterator object for iterating over routes */ public function getIterator() { return new \ArrayIterator($this->routes); } /** * Gets the number of Routes in this collection. * * @return int The number of routes */ public function count() { return count($this->routes); } /** * Adds a route. * * @param string $name The route name * @param Route $route A Route instance * * @api */ public function add($name, Route $route) { unset($this->routes[$name]); $this->routes[$name] = $route; } /** * Returns all routes in this collection. * * @return Route[] An array of routes */ public function all() { return $this->routes; } /** * Gets a route by name. * * @param string $name The route name * * @return Route|null A Route instance or null when not found */ public function get($name) { return isset($this->routes[$name]) ? $this->routes[$name] : null; } /** * Removes a route or an array of routes by name from the collection * * @param string|array $name The route name or an array of route names */ public function remove($name) { foreach ((array) $name as $n) { unset($this->routes[$n]); } } /** * Adds a route collection at the end of the current set by appending all * routes of the added collection. * * @param RouteCollection $collection A RouteCollection instance * * @api */ public function addCollection(RouteCollection $collection) { // we need to remove all routes with the same names first because just replacing them // would not place the new route at the end of the merged array foreach ($collection->all() as $name => $route) { unset($this->routes[$name]); $this->routes[$name] = $route; } $this->resources = array_merge($this->resources, $collection->getResources()); } /** * Adds a prefix to the path of all child routes. * * @param string $prefix An optional prefix to add before each pattern of the route collection * @param array $defaults An array of default values * @param array $requirements An array of requirements * * @api */ public function addPrefix($prefix, array $defaults = array(), array $requirements = array()) { $prefix = trim(trim($prefix), '/'); if ('' === $prefix) { return; } foreach ($this->routes as $route) { $route->setPath('/'.$prefix.$route->getPath()); $route->addDefaults($defaults); $route->addRequirements($requirements); } } /** * Sets the host pattern on all routes. * * @param string $pattern The pattern * @param array $defaults An array of default values * @param array $requirements An array of requirements */ public function setHost($pattern, array $defaults = array(), array $requirements = array()) { foreach ($this->routes as $route) { $route->setHost($pattern); $route->addDefaults($defaults); $route->addRequirements($requirements); } } /** * Sets a condition on all routes. * * Existing conditions will be overridden. * * @param string $condition The condition */ public function setCondition($condition) { foreach ($this->routes as $route) { $route->setCondition($condition); } } /** * Adds defaults to all routes. * * An existing default value under the same name in a route will be overridden. * * @param array $defaults An array of default values */ public function addDefaults(array $defaults) { if ($defaults) { foreach ($this->routes as $route) { $route->addDefaults($defaults); } } } /** * Adds requirements to all routes. * * An existing requirement under the same name in a route will be overridden. * * @param array $requirements An array of requirements */ public function addRequirements(array $requirements) { if ($requirements) { foreach ($this->routes as $route) { $route->addRequirements($requirements); } } } /** * Adds options to all routes. * * An existing option value under the same name in a route will be overridden. * * @param array $options An array of options */ public function addOptions(array $options) { if ($options) { foreach ($this->routes as $route) { $route->addOptions($options); } } } /** * Sets the schemes (e.g. 'https') all child routes are restricted to. * * @param string|array $schemes The scheme or an array of schemes */ public function setSchemes($schemes) { foreach ($this->routes as $route) { $route->setSchemes($schemes); } } /** * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to. * * @param string|array $methods The method or an array of methods */ public function setMethods($methods) { foreach ($this->routes as $route) { $route->setMethods($methods); } } /** * Returns an array of resources loaded to build this collection. * * @return ResourceInterface[] An array of resources */ public function getResources() { return array_unique($this->resources); } /** * Adds a resource for this collection. * * @param ResourceInterface $resource A resource instance */ public function addResource(ResourceInterface $resource) { $this->resources[] = $resource; } } PK]&%L L "Security/Csrf/CsrfTokenManager.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf; use Symfony\Component\Security\Core\Util\StringUtils; use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator; use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface; use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage; use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface; /** * Default implementation of {@link CsrfTokenManagerInterface}. * * @author Bernhard Schussek */ class CsrfTokenManager implements CsrfTokenManagerInterface { /** * @var TokenGeneratorInterface */ private $generator; /** * @var TokenStorageInterface */ private $storage; /** * Creates a new CSRF provider using PHP's native session storage. * * @param TokenGeneratorInterface|null $generator The token generator * @param TokenStorageInterface|null $storage The storage for storing * generated CSRF tokens */ public function __construct(TokenGeneratorInterface $generator = null, TokenStorageInterface $storage = null) { $this->generator = $generator ?: new UriSafeTokenGenerator(); $this->storage = $storage ?: new NativeSessionTokenStorage(); } /** * {@inheritdoc} */ public function getToken($tokenId) { if ($this->storage->hasToken($tokenId)) { $value = $this->storage->getToken($tokenId); } else { $value = $this->generator->generateToken(); $this->storage->setToken($tokenId, $value); } return new CsrfToken($tokenId, $value); } /** * {@inheritdoc} */ public function refreshToken($tokenId) { $value = $this->generator->generateToken(); $this->storage->setToken($tokenId, $value); return new CsrfToken($tokenId, $value); } /** * {@inheritdoc} */ public function removeToken($tokenId) { return $this->storage->removeToken($tokenId); } /** * {@inheritdoc} */ public function isTokenValid(CsrfToken $token) { if (!$this->storage->hasToken($token->getId())) { return false; } return StringUtils::equals($this->storage->getToken($token->getId()), $token->getValue()); } } PK]VǴ+Security/Csrf/CsrfTokenManagerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf; /** * Manages CSRF tokens. * * @since 2.4 * @author Bernhard Schussek */ interface CsrfTokenManagerInterface { /** * Returns a CSRF token for the given ID. * * If previously no token existed for the given ID, a new token is * generated. Otherwise the existing token is returned (with the same value, * not the same instance). * * @param string $tokenId The token ID. You may choose an arbitrary value * for the ID * * @return CsrfToken The CSRF token */ public function getToken($tokenId); /** * Generates a new token value for the given ID. * * This method will generate a new token for the given token ID, independent * of whether a token value previously existed or not. It can be used to * enforce once-only tokens in environments with high security needs. * * @param string $tokenId The token ID. You may choose an arbitrary value * for the ID * * @return CsrfToken The CSRF token */ public function refreshToken($tokenId); /** * Invalidates the CSRF token with the given ID, if one exists. * * @param string $tokenId The token ID * * @return string|null Returns the removed token value if one existed, NULL * otherwise */ public function removeToken($tokenId); /** * Returns whether the given CSRF token is valid. * * @param CsrfToken $token A CSRF token * * @return Boolean Returns true if the token is valid, false otherwise */ public function isTokenValid(CsrfToken $token); } PK] 8Security/Csrf/TokenStorage/NativeSessionTokenStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\TokenStorage; use Symfony\Component\Security\Csrf\Exception\TokenNotFoundException; /** * Token storage that uses PHP's native session handling. * * @since 2.4 * @author Bernhard Schussek */ class NativeSessionTokenStorage implements TokenStorageInterface { /** * The namespace used to store values in the session. * @var string */ const SESSION_NAMESPACE = '_csrf'; /** * @var Boolean */ private $sessionStarted = false; /** * @var string */ private $namespace; /** * Initializes the storage with a session namespace. * * @param string $namespace The namespace under which the token is stored * in the session */ public function __construct($namespace = self::SESSION_NAMESPACE) { $this->namespace = $namespace; } /** * {@inheritdoc} */ public function getToken($tokenId) { if (!$this->sessionStarted) { $this->startSession(); } if (!isset($_SESSION[$this->namespace][$tokenId])) { throw new TokenNotFoundException('The CSRF token with ID '.$tokenId.' does not exist.'); } return (string) $_SESSION[$this->namespace][$tokenId]; } /** * {@inheritdoc} */ public function setToken($tokenId, $token) { if (!$this->sessionStarted) { $this->startSession(); } $_SESSION[$this->namespace][$tokenId] = (string) $token; } /** * {@inheritdoc} */ public function hasToken($tokenId) { if (!$this->sessionStarted) { $this->startSession(); } return isset($_SESSION[$this->namespace][$tokenId]); } /** * {@inheritdoc} */ public function removeToken($tokenId) { if (!$this->sessionStarted) { $this->startSession(); } $token = isset($_SESSION[$this->namespace][$tokenId]) ? (string) $_SESSION[$this->namespace][$tokenId] : null; unset($_SESSION[$this->namespace][$tokenId]); return $token; } private function startSession() { if (version_compare(PHP_VERSION, '5.4', '>=')) { if (PHP_SESSION_NONE === session_status()) { session_start(); } } elseif (!session_id()) { session_start(); } $this->sessionStarted = true; } } PK]4Security/Csrf/TokenStorage/TokenStorageInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\TokenStorage; /** * Stores CSRF tokens. * * @since 2.4 * @author Bernhard Schussek */ interface TokenStorageInterface { /** * Reads a stored CSRF token. * * @param string $tokenId The token ID * * @return string The stored token * * @throws \Symfony\Component\Security\Csrf\Exception\TokenNotFoundException If the token ID does not exist */ public function getToken($tokenId); /** * Stores a CSRF token. * * @param string $tokenId The token ID * @param string $token The CSRF token */ public function setToken($tokenId, $token); /** * Removes a CSRF token. * * @param string $tokenId The token ID * * @return string|null Returns the removed token if one existed, NULL * otherwise */ public function removeToken($tokenId); /** * Checks whether a token with the given token ID exists. * * @param string $tokenId The token ID * * @return Boolean Whether a token exists with the given ID */ public function hasToken($tokenId); } PK]]N N 2Security/Csrf/TokenStorage/SessionTokenStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\TokenStorage; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\Security\Csrf\Exception\TokenNotFoundException; /** * Token storage that uses a Symfony2 Session object. * * @since 2.4 * @author Bernhard Schussek */ class SessionTokenStorage implements TokenStorageInterface { /** * The namespace used to store values in the session. * @var string */ const SESSION_NAMESPACE = '_csrf'; /** * The user session from which the session ID is returned * @var SessionInterface */ private $session; /** * @var string */ private $namespace; /** * Initializes the storage with a Session object and a session namespace. * * @param SessionInterface $session The user session * @param string $namespace The namespace under which the token * is stored in the session */ public function __construct(SessionInterface $session, $namespace = self::SESSION_NAMESPACE) { $this->session = $session; $this->namespace = $namespace; } /** * {@inheritdoc} */ public function getToken($tokenId) { if (!$this->session->isStarted()) { $this->session->start(); } if (!$this->session->has($this->namespace.'/'.$tokenId)) { throw new TokenNotFoundException('The CSRF token with ID '.$tokenId.' does not exist.'); } return (string) $this->session->get($this->namespace.'/'.$tokenId); } /** * {@inheritdoc} */ public function setToken($tokenId, $token) { if (!$this->session->isStarted()) { $this->session->start(); } $this->session->set($this->namespace.'/'.$tokenId, (string) $token); } /** * {@inheritdoc} */ public function hasToken($tokenId) { if (!$this->session->isStarted()) { $this->session->start(); } return $this->session->has($this->namespace.'/'.$tokenId); } /** * {@inheritdoc} */ public function removeToken($tokenId) { if (!$this->session->isStarted()) { $this->session->start(); } return $this->session->remove($this->namespace.'/'.$tokenId); } } PK]eI2Security/Csrf/Exception/TokenNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\Exception; use Symfony\Component\Security\Core\Exception\RuntimeException; /** * @author Bernhard Schussek */ class TokenNotFoundException extends RuntimeException { } PK] =6Security/Csrf/TokenGenerator/UriSafeTokenGenerator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\TokenGenerator; use Symfony\Component\Security\Core\Util\SecureRandomInterface; use Symfony\Component\Security\Core\Util\SecureRandom; /** * Generates CSRF tokens. * * @since 2.4 * @author Bernhard Schussek */ class UriSafeTokenGenerator implements TokenGeneratorInterface { /** * The generator for random values. * * @var SecureRandomInterface */ private $random; /** * The amount of entropy collected for each token (in bits). * * @var integer */ private $entropy; /** * Generates URI-safe CSRF tokens. * * @param SecureRandomInterface|null $random The random value generator used for * generating entropy * @param integer $entropy The amount of entropy collected for * each token (in bits) */ public function __construct(SecureRandomInterface $random = null, $entropy = 256) { $this->random = $random ?: new SecureRandom(); $this->entropy = $entropy; } /** * {@inheritdoc} */ public function generateToken() { // Generate an URI safe base64 encoded string that does not contain "+", // "/" or "=" which need to be URL encoded and make URLs unnecessarily // longer. $bytes = $this->random->nextBytes($this->entropy / 8); return rtrim(strtr(base64_encode($bytes), '+/', '-_'), '='); } } PK]J,p8Security/Csrf/TokenGenerator/TokenGeneratorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\TokenGenerator; /** * Generates and validates CSRF tokens. * * You can generate a CSRF token by using the method {@link generateCsrfToken()}. * This method expects a unique token ID as argument. The token ID can later be * used to validate a token provided by the user. * * Token IDs do not necessarily have to be secret, but they should NEVER be * created from data provided by the client. A good practice is to hard-code the * token IDs for the various CSRF tokens used by your application. * * You should use the method {@link isCsrfTokenValid()} to check a CSRF token * submitted by the client. This method will return true if the CSRF token is * valid. * * @since 2.4 * @author Bernhard Schussek */ interface TokenGeneratorInterface { /** * Generates a CSRF token. * * @return string The generated CSRF token */ public function generateToken(); } PK]OSecurity/Csrf/CsrfToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf; /** * A CSRF token. * * @author Bernhard Schussek */ class CsrfToken { /** * @var string */ private $id; /** * @var string */ private $value; /** * Constructor. * * @param string $id The token ID * @param string $value The actual token value */ public function __construct($id, $value) { $this->id = (string) $id; $this->value = (string) $value; } /** * Returns the ID of the CSRF token. * * @return string The token ID */ public function getId() { return $this->id; } /** * Returns the value of the CSRF token. * * @return string The token value */ public function getValue() { return $this->value; } /** * Returns the value of the CSRF token. * * @return string The token value */ public function __toString() { return $this->value; } } PK]"CSecurity/Http/FirewallMap.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\HttpFoundation\RequestMatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Http\Firewall\ExceptionListener; /** * FirewallMap allows configuration of different firewalls for specific parts * of the website. * * @author Fabien Potencier */ class FirewallMap implements FirewallMapInterface { private $map = array(); /** * @param RequestMatcherInterface $requestMatcher * @param array $listeners * @param ExceptionListener $exceptionListener */ public function add(RequestMatcherInterface $requestMatcher = null, array $listeners = array(), ExceptionListener $exceptionListener = null) { $this->map[] = array($requestMatcher, $listeners, $exceptionListener); } /** * {@inheritDoc} */ public function getListeners(Request $request) { foreach ($this->map as $elements) { if (null === $elements[0] || $elements[0]->matches($request)) { return array($elements[1], $elements[2]); } } return array(array(), null); } } PK]:&GG@Security/Http/Session/SessionAuthenticationStrategyInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Session; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Request; /** * SessionAuthenticationStrategyInterface * * Implementation are responsible for updating the session after an interactive * authentication attempt was successful. * * @author Johannes M. Schmitt */ interface SessionAuthenticationStrategyInterface { /** * This performs any necessary changes to the session. * * This method is called before the SecurityContext is populated with a * Token, and only by classes inheriting from AbstractAuthenticationListener. * * @param Request $request * @param TokenInterface $token */ public function onAuthentication(Request $request, TokenInterface $token); } PK]La[[7Security/Http/Session/SessionAuthenticationStrategy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Session; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Request; /** * The default session strategy implementation. * * Supports the following strategies: * NONE: the session is not changed * MIGRATE: the session id is updated, attributes are kept * INVALIDATE: the session id is updated, attributes are lost * * @author Johannes M. Schmitt */ class SessionAuthenticationStrategy implements SessionAuthenticationStrategyInterface { const NONE = 'none'; const MIGRATE = 'migrate'; const INVALIDATE = 'invalidate'; private $strategy; public function __construct($strategy) { $this->strategy = $strategy; } /** * {@inheritDoc} */ public function onAuthentication(Request $request, TokenInterface $token) { switch ($this->strategy) { case self::NONE: return; case self::MIGRATE: $request->getSession()->migrate(); return; case self::INVALIDATE: $request->getSession()->invalidate(); return; default: throw new \RuntimeException(sprintf('Invalid session authentication strategy "%s"', $this->strategy)); } } } PK]\\&Security/Http/FirewallMapInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\HttpFoundation\Request; /** * This interface must be implemented by firewall maps. * * @author Johannes M. Schmitt */ interface FirewallMapInterface { /** * Returns the authentication listeners, and the exception listener to use * for the given request. * * If there are no authentication listeners, the first inner array must be * empty. * * If there is no exception listener, the second element of the outer array * must be null. * * @param Request $request * * @return array of the format array(array(AuthenticationListener), ExceptionListener) */ public function getListeners(Request $request); } PK] 6'6'9Security/Http/Firewall/AbstractAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\SessionUnavailableException; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\Security\Http\HttpUtils; /** * The AbstractAuthenticationListener is the preferred base class for all * browser-/HTTP-based authentication requests. * * Subclasses likely have to implement the following: * - an TokenInterface to hold authentication related data * - an AuthenticationProvider to perform the actual authentication of the * token, retrieve the UserInterface implementation from a database, and * perform the specific account checks using the UserChecker * * By default, this listener only is active for a specific path, e.g. * /login_check. If you want to change this behavior, you can overwrite the * requiresAuthentication() method. * * @author Fabien Potencier * @author Johannes M. Schmitt */ abstract class AbstractAuthenticationListener implements ListenerInterface { protected $options; protected $logger; protected $authenticationManager; protected $providerKey; protected $httpUtils; private $securityContext; private $sessionStrategy; private $dispatcher; private $successHandler; private $failureHandler; private $rememberMeServices; /** * Constructor. * * @param SecurityContextInterface $securityContext A SecurityContext instance * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance * @param SessionAuthenticationStrategyInterface $sessionStrategy * @param HttpUtils $httpUtils An HttpUtilsInterface instance * @param string $providerKey * @param AuthenticationSuccessHandlerInterface $successHandler * @param AuthenticationFailureHandlerInterface $failureHandler * @param array $options An array of options for the processing of a * successful, or failed authentication attempt * @param LoggerInterface $logger A LoggerInterface instance * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * * @throws \InvalidArgumentException */ public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->securityContext = $securityContext; $this->authenticationManager = $authenticationManager; $this->sessionStrategy = $sessionStrategy; $this->providerKey = $providerKey; $this->successHandler = $successHandler; $this->failureHandler = $failureHandler; $this->options = array_merge(array( 'check_path' => '/login_check', 'login_path' => '/login', 'always_use_default_target_path' => false, 'default_target_path' => '/', 'target_path_parameter' => '_target_path', 'use_referer' => false, 'failure_path' => null, 'failure_forward' => false, 'require_previous_session' => true, ), $options); $this->logger = $logger; $this->dispatcher = $dispatcher; $this->httpUtils = $httpUtils; } /** * Sets the RememberMeServices implementation to use * * @param RememberMeServicesInterface $rememberMeServices */ public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices) { $this->rememberMeServices = $rememberMeServices; } /** * Handles form based authentication. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws \RuntimeException * @throws SessionUnavailableException */ final public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (!$this->requiresAuthentication($request)) { return; } if (!$request->hasSession()) { throw new \RuntimeException('This authentication method requires a session.'); } try { if ($this->options['require_previous_session'] && !$request->hasPreviousSession()) { throw new SessionUnavailableException('Your session has timed out, or you have disabled cookies.'); } if (null === $returnValue = $this->attemptAuthentication($request)) { return; } if ($returnValue instanceof TokenInterface) { $this->sessionStrategy->onAuthentication($request, $returnValue); $response = $this->onSuccess($event, $request, $returnValue); } elseif ($returnValue instanceof Response) { $response = $returnValue; } else { throw new \RuntimeException('attemptAuthentication() must either return a Response, an implementation of TokenInterface, or null.'); } } catch (AuthenticationException $e) { $response = $this->onFailure($event, $request, $e); } $event->setResponse($response); } /** * Whether this request requires authentication. * * The default implementation only processes requests to a specific path, * but a subclass could change this to only authenticate requests where a * certain parameters is present. * * @param Request $request * * @return Boolean */ protected function requiresAuthentication(Request $request) { return $this->httpUtils->checkRequestPath($request, $this->options['check_path']); } /** * Performs authentication. * * @param Request $request A Request instance * * @return TokenInterface|Response|null The authenticated token, null if full authentication is not possible, or a Response * * @throws AuthenticationException if the authentication fails */ abstract protected function attemptAuthentication(Request $request); private function onFailure(GetResponseEvent $event, Request $request, AuthenticationException $failed) { if (null !== $this->logger) { $this->logger->info(sprintf('Authentication request failed: %s', $failed->getMessage())); } $token = $this->securityContext->getToken(); if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) { $this->securityContext->setToken(null); } $response = $this->failureHandler->onAuthenticationFailure($request, $failed); if (!$response instanceof Response) { throw new \RuntimeException('Authentication Failure Handler did not return a Response.'); } return $response; } private function onSuccess(GetResponseEvent $event, Request $request, TokenInterface $token) { if (null !== $this->logger) { $this->logger->info(sprintf('User "%s" has been authenticated successfully', $token->getUsername())); } $this->securityContext->setToken($token); $session = $request->getSession(); $session->remove(SecurityContextInterface::AUTHENTICATION_ERROR); $session->remove(SecurityContextInterface::LAST_USERNAME); if (null !== $this->dispatcher) { $loginEvent = new InteractiveLoginEvent($request, $token); $this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent); } $response = $this->successHandler->onAuthenticationSuccess($request, $token); if (!$response instanceof Response) { throw new \RuntimeException('Authentication Success Handler did not return a Response.'); } if (null !== $this->rememberMeServices) { $this->rememberMeServices->loginSuccess($request, $response, $token); } return $response; } } PK]"?*Security/Http/Firewall/ContextListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * ContextListener manages the SecurityContext persistence through a session. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class ContextListener implements ListenerInterface { private $context; private $contextKey; private $logger; private $userProviders; private $dispatcher; private $registered; public function __construct(SecurityContextInterface $context, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { if (empty($contextKey)) { throw new \InvalidArgumentException('$contextKey must not be empty.'); } foreach ($userProviders as $userProvider) { if (!$userProvider instanceof UserProviderInterface) { throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "Symfony\Component\Security\Core\User\UserProviderInterface".', get_class($userProvider))); } } $this->context = $context; $this->userProviders = $userProviders; $this->contextKey = $contextKey; $this->logger = $logger; $this->dispatcher = $dispatcher; } /** * Reads the SecurityContext from the session. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { if (!$this->registered && null !== $this->dispatcher && $event->isMasterRequest()) { $this->dispatcher->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse')); $this->registered = true; } $request = $event->getRequest(); $session = $request->hasPreviousSession() ? $request->getSession() : null; if (null === $session || null === $token = $session->get('_security_'.$this->contextKey)) { $this->context->setToken(null); return; } $token = unserialize($token); if (null !== $this->logger) { $this->logger->debug('Read SecurityContext from the session'); } if ($token instanceof TokenInterface) { $token = $this->refreshUser($token); } elseif (null !== $token) { if (null !== $this->logger) { $this->logger->warning(sprintf('Session includes a "%s" where a security token is expected', is_object($token) ? get_class($token) : gettype($token))); } $token = null; } $this->context->setToken($token); } /** * Writes the SecurityContext to the session. * * @param FilterResponseEvent $event A FilterResponseEvent instance */ public function onKernelResponse(FilterResponseEvent $event) { if (!$event->isMasterRequest()) { return; } if (!$event->getRequest()->hasSession()) { return; } if (null !== $this->logger) { $this->logger->debug('Write SecurityContext in the session'); } $request = $event->getRequest(); $session = $request->getSession(); if (null === $session) { return; } if ((null === $token = $this->context->getToken()) || ($token instanceof AnonymousToken)) { if ($request->hasPreviousSession()) { $session->remove('_security_'.$this->contextKey); } } else { $session->set('_security_'.$this->contextKey, serialize($token)); } } /** * Refreshes the user by reloading it from the user provider * * @param TokenInterface $token * * @return TokenInterface|null * * @throws \RuntimeException */ private function refreshUser(TokenInterface $token) { $user = $token->getUser(); if (!$user instanceof UserInterface) { return $token; } if (null !== $this->logger) { $this->logger->debug(sprintf('Reloading user from user provider.')); } foreach ($this->userProviders as $provider) { try { $refreshedUser = $provider->refreshUser($user); $token->setUser($refreshedUser); if (null !== $this->logger) { $this->logger->debug(sprintf('Username "%s" was reloaded from user provider.', $refreshedUser->getUsername())); } return $token; } catch (UnsupportedUserException $unsupported) { // let's try the next user provider } catch (UsernameNotFoundException $notFound) { if (null !== $this->logger) { $this->logger->warning(sprintf('Username "%s" could not be found.', $notFound->getUsername())); } return null; } } throw new \RuntimeException(sprintf('There is no user provider for user "%s".', get_class($user))); } } PK]Z;Security/Http/Firewall/AbstractPreAuthenticatedListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Security\Core\Exception\BadCredentialsException; /** * AbstractPreAuthenticatedListener is the base class for all listener that * authenticates users based on a pre-authenticated request (like a certificate * for instance). * * @author Fabien Potencier */ abstract class AbstractPreAuthenticatedListener implements ListenerInterface { protected $logger; private $securityContext; private $authenticationManager; private $providerKey; private $dispatcher; public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { $this->securityContext = $securityContext; $this->authenticationManager = $authenticationManager; $this->providerKey = $providerKey; $this->logger = $logger; $this->dispatcher = $dispatcher; } /** * Handles pre-authentication. * * @param GetResponseEvent $event A GetResponseEvent instance */ final public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (null !== $this->logger) { $this->logger->debug(sprintf('Checking secure context token: %s', $this->securityContext->getToken())); } try { list($user, $credentials) = $this->getPreAuthenticatedData($request); } catch (BadCredentialsException $exception) { $this->clearToken($exception); return; } if (null !== $token = $this->securityContext->getToken()) { if ($token instanceof PreAuthenticatedToken && $this->providerKey == $token->getProviderKey() && $token->isAuthenticated() && $token->getUsername() === $user) { return; } } if (null !== $this->logger) { $this->logger->debug(sprintf('Trying to pre-authenticate user "%s"', $user)); } try { $token = $this->authenticationManager->authenticate(new PreAuthenticatedToken($user, $credentials, $this->providerKey)); if (null !== $this->logger) { $this->logger->info(sprintf('Authentication success: %s', $token)); } $this->securityContext->setToken($token); if (null !== $this->dispatcher) { $loginEvent = new InteractiveLoginEvent($request, $token); $this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent); } } catch (AuthenticationException $failed) { $this->clearToken($failed); } } /** * Clears a PreAuthenticatedToken for this provider (if present) * * @param AuthenticationException $exception */ private function clearToken(AuthenticationException $exception) { $token = $this->securityContext->getToken(); if ($token instanceof PreAuthenticatedToken && $this->providerKey === $token->getProviderKey()) { $this->securityContext->setToken(null); if (null !== $this->logger) { $this->logger->info(sprintf("Cleared security context due to exception: %s", $exception->getMessage())); } } } /** * Gets the user and credentials from the Request. * * @param Request $request A Request instance * * @return array An array composed of the user and the credentials */ abstract protected function getPreAuthenticatedData(Request $request); } PK]&! 6Security/Http/Firewall/BasicAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; /** * BasicAuthenticationListener implements Basic HTTP authentication. * * @author Fabien Potencier */ class BasicAuthenticationListener implements ListenerInterface { private $securityContext; private $authenticationManager; private $providerKey; private $authenticationEntryPoint; private $logger; private $ignoreFailure; public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->securityContext = $securityContext; $this->authenticationManager = $authenticationManager; $this->providerKey = $providerKey; $this->authenticationEntryPoint = $authenticationEntryPoint; $this->logger = $logger; $this->ignoreFailure = false; } /** * Handles basic authentication. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (false === $username = $request->headers->get('PHP_AUTH_USER', false)) { return; } if (null !== $token = $this->securityContext->getToken()) { if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && $token->getUsername() === $username) { return; } } if (null !== $this->logger) { $this->logger->info(sprintf('Basic Authentication Authorization header found for user "%s"', $username)); } try { $token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey)); $this->securityContext->setToken($token); } catch (AuthenticationException $failed) { $token = $this->securityContext->getToken(); if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) { $this->securityContext->setToken(null); } if (null !== $this->logger) { $this->logger->info(sprintf('Authentication request failed for user "%s": %s', $username, $failed->getMessage())); } if ($this->ignoreFailure) { return; } $event->setResponse($this->authenticationEntryPoint->start($request, $failed)); } } } PK]B b  -Security/Http/Firewall/SwitchUserListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Role\SwitchUserRole; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Http\Event\SwitchUserEvent; use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * SwitchUserListener allows a user to impersonate another one temporarily * (like the Unix su command). * * @author Fabien Potencier */ class SwitchUserListener implements ListenerInterface { private $securityContext; private $provider; private $userChecker; private $providerKey; private $accessDecisionManager; private $usernameParameter; private $role; private $logger; private $dispatcher; /** * Constructor. */ public function __construct(SecurityContextInterface $securityContext, UserProviderInterface $provider, UserCheckerInterface $userChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH', EventDispatcherInterface $dispatcher = null) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->securityContext = $securityContext; $this->provider = $provider; $this->userChecker = $userChecker; $this->providerKey = $providerKey; $this->accessDecisionManager = $accessDecisionManager; $this->usernameParameter = $usernameParameter; $this->role = $role; $this->logger = $logger; $this->dispatcher = $dispatcher; } /** * Handles the switch to another user. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws \LogicException if switching to a user failed */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (!$request->get($this->usernameParameter)) { return; } if ('_exit' === $request->get($this->usernameParameter)) { $this->securityContext->setToken($this->attemptExitUser($request)); } else { try { $this->securityContext->setToken($this->attemptSwitchUser($request)); } catch (AuthenticationException $e) { throw new \LogicException(sprintf('Switch User failed: "%s"', $e->getMessage())); } } $request->query->remove($this->usernameParameter); $request->server->set('QUERY_STRING', http_build_query($request->query->all())); $response = new RedirectResponse($request->getUri(), 302); $event->setResponse($response); } /** * Attempts to switch to another user. * * @param Request $request A Request instance * * @return TokenInterface|null The new TokenInterface if successfully switched, null otherwise * * @throws \LogicException * @throws AccessDeniedException */ private function attemptSwitchUser(Request $request) { $token = $this->securityContext->getToken(); $originalToken = $this->getOriginalToken($token); if (false !== $originalToken) { if ($token->getUsername() === $request->get($this->usernameParameter)) { return $token; } else { throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername())); } } if (false === $this->accessDecisionManager->decide($token, array($this->role))) { throw new AccessDeniedException(); } $username = $request->get($this->usernameParameter); if (null !== $this->logger) { $this->logger->info(sprintf('Attempt to switch to user "%s"', $username)); } $user = $this->provider->loadUserByUsername($username); $this->userChecker->checkPostAuth($user); $roles = $user->getRoles(); $roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $this->securityContext->getToken()); $token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey, $roles); if (null !== $this->dispatcher) { $switchEvent = new SwitchUserEvent($request, $token->getUser()); $this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent); } return $token; } /** * Attempts to exit from an already switched user. * * @param Request $request A Request instance * * @return TokenInterface The original TokenInterface instance * * @throws AuthenticationCredentialsNotFoundException */ private function attemptExitUser(Request $request) { if (false === $original = $this->getOriginalToken($this->securityContext->getToken())) { throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.'); } if (null !== $this->dispatcher) { $switchEvent = new SwitchUserEvent($request, $original->getUser()); $this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent); } return $original; } /** * Gets the original Token from a switched one. * * @param TokenInterface $token A switched TokenInterface instance * * @return TokenInterface|false The original TokenInterface instance, false if the current TokenInterface is not switched */ private function getOriginalToken(TokenInterface $token) { foreach ($token->getRoles() as $role) { if ($role instanceof SwitchUserRole) { return $role->getSource(); } } return false; } } PK];Security/Http/Firewall/SimpleFormAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\InvalidArgumentException; use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; use Psr\Log\LoggerInterface; /** * @author Jordi Boggiano */ class SimpleFormAuthenticationListener extends AbstractAuthenticationListener { private $simpleAuthenticator; private $csrfTokenManager; /** * Constructor. * * @param SecurityContextInterface $securityContext A SecurityContext instance * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance * @param SessionAuthenticationStrategyInterface $sessionStrategy * @param HttpUtils $httpUtils An HttpUtilsInterface instance * @param string $providerKey * @param AuthenticationSuccessHandlerInterface $successHandler * @param AuthenticationFailureHandlerInterface $failureHandler * @param array $options An array of options for the processing of a * successful, or failed authentication attempt * @param LoggerInterface $logger A LoggerInterface instance * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param SimpleFormAuthenticatorInterface $simpleAuthenticator A SimpleFormAuthenticatorInterface instance * @param CsrfTokenManagerInterface $csrfTokenManager A CsrfTokenManagerInterface instance */ public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfTokenManagerInterface $csrfTokenManager = null, SimpleFormAuthenticatorInterface $simpleAuthenticator = null) { if (!$simpleAuthenticator) { throw new \InvalidArgumentException('Missing simple authenticator'); } if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new InvalidArgumentException('The CSRF token manager should be an instance of CsrfProviderInterface or CsrfTokenManagerInterface.'); } $this->simpleAuthenticator = $simpleAuthenticator; $this->csrfTokenManager = $csrfTokenManager; $options = array_merge(array( 'username_parameter' => '_username', 'password_parameter' => '_password', 'csrf_parameter' => '_csrf_token', 'intention' => 'authenticate', 'post_only' => true, ), $options); parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, $options, $logger, $dispatcher); } /** * {@inheritdoc} */ protected function requiresAuthentication(Request $request) { if ($this->options['post_only'] && !$request->isMethod('POST')) { return false; } return parent::requiresAuthentication($request); } /** * {@inheritdoc} */ protected function attemptAuthentication(Request $request) { if (null !== $this->csrfTokenManager) { $csrfToken = $request->get($this->options['csrf_parameter'], null, true); if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['intention'], $csrfToken))) { throw new InvalidCsrfTokenException('Invalid CSRF token.'); } } if ($this->options['post_only']) { $username = trim($request->request->get($this->options['username_parameter'], null, true)); $password = $request->request->get($this->options['password_parameter'], null, true); } else { $username = trim($request->get($this->options['username_parameter'], null, true)); $password = $request->get($this->options['password_parameter'], null, true); } $request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username); $token = $this->simpleAuthenticator->createToken($request, $username, $password, $this->providerKey); return $this->authenticationManager->authenticate($token); } } PK](T b!b!,Security/Http/Firewall/ExceptionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Symfony\Component\Security\Core\Exception\AccountStatusException; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException; use Symfony\Component\Security\Core\Exception\LogoutException; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\HttpFoundation\Request; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * ExceptionListener catches authentication exception and converts them to * Response instances. * * @author Fabien Potencier */ class ExceptionListener { private $context; private $providerKey; private $accessDeniedHandler; private $authenticationEntryPoint; private $authenticationTrustResolver; private $errorPage; private $logger; private $httpUtils; public function __construct(SecurityContextInterface $context, AuthenticationTrustResolverInterface $trustResolver, HttpUtils $httpUtils, $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint = null, $errorPage = null, AccessDeniedHandlerInterface $accessDeniedHandler = null, LoggerInterface $logger = null) { $this->context = $context; $this->accessDeniedHandler = $accessDeniedHandler; $this->httpUtils = $httpUtils; $this->providerKey = $providerKey; $this->authenticationEntryPoint = $authenticationEntryPoint; $this->authenticationTrustResolver = $trustResolver; $this->errorPage = $errorPage; $this->logger = $logger; } /** * Registers a onKernelException listener to take care of security exceptions. * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance */ public function register(EventDispatcherInterface $dispatcher) { $dispatcher->addListener(KernelEvents::EXCEPTION, array($this, 'onKernelException')); } /** * Unregisters the dispatcher. * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance */ public function unregister(EventDispatcherInterface $dispatcher) { $dispatcher->removeListener(KernelEvents::EXCEPTION, array($this, 'onKernelException')); } /** * Handles security related exceptions. * * @param GetResponseForExceptionEvent $event An GetResponseForExceptionEvent instance */ public function onKernelException(GetResponseForExceptionEvent $event) { $exception = $event->getException(); do { if ($exception instanceof AuthenticationException) { return $this->handleAuthenticationException($event, $exception); } elseif ($exception instanceof AccessDeniedException) { return $this->handleAccessDeniedException($event, $exception); } elseif ($exception instanceof LogoutException) { return $this->handleLogoutException($event, $exception); } } while (null !== $exception = $exception->getPrevious()); } private function handleAuthenticationException(GetResponseForExceptionEvent $event, AuthenticationException $exception) { if (null !== $this->logger) { $this->logger->info(sprintf('Authentication exception occurred; redirecting to authentication entry point (%s)', $exception->getMessage())); } try { $event->setResponse($this->startAuthentication($event->getRequest(), $exception)); } catch (\Exception $e) { $event->setException($e); } } private function handleAccessDeniedException(GetResponseForExceptionEvent $event, AccessDeniedException $exception) { $event->setException(new AccessDeniedHttpException($exception->getMessage(), $exception)); $token = $this->context->getToken(); if (!$this->authenticationTrustResolver->isFullFledged($token)) { if (null !== $this->logger) { $this->logger->debug(sprintf('Access is denied (user is not fully authenticated) by "%s" at line %s; redirecting to authentication entry point', $exception->getFile(), $exception->getLine())); } try { $insufficientAuthenticationException = new InsufficientAuthenticationException('Full authentication is required to access this resource.', 0, $exception); $insufficientAuthenticationException->setToken($token); $event->setResponse($this->startAuthentication($event->getRequest(), $insufficientAuthenticationException)); } catch (\Exception $e) { $event->setException($e); } return; } if (null !== $this->logger) { $this->logger->debug(sprintf('Access is denied (and user is neither anonymous, nor remember-me) by "%s" at line %s', $exception->getFile(), $exception->getLine())); } try { if (null !== $this->accessDeniedHandler) { $response = $this->accessDeniedHandler->handle($event->getRequest(), $exception); if ($response instanceof Response) { $event->setResponse($response); } } elseif (null !== $this->errorPage) { $subRequest = $this->httpUtils->createRequest($event->getRequest(), $this->errorPage); $subRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $exception); $event->setResponse($event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true)); } } catch (\Exception $e) { if (null !== $this->logger) { $this->logger->error(sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage())); } $event->setException(new \RuntimeException('Exception thrown when handling an exception.', 0, $e)); } } private function handleLogoutException(GetResponseForExceptionEvent $event, LogoutException $exception) { if (null !== $this->logger) { $this->logger->info(sprintf('Logout exception occurred; wrapping with AccessDeniedHttpException (%s)', $exception->getMessage())); } } /** * @param Request $request * @param AuthenticationException $authException * * @return Response * @throws AuthenticationException */ private function startAuthentication(Request $request, AuthenticationException $authException) { if (null === $this->authenticationEntryPoint) { throw $authException; } if (null !== $this->logger) { $this->logger->debug('Calling Authentication entry point'); } $this->setTargetPath($request); if ($authException instanceof AccountStatusException) { // remove the security token to prevent infinite redirect loops $this->context->setToken(null); } return $this->authenticationEntryPoint->start($request, $authException); } /** * @param Request $request */ protected function setTargetPath(Request $request) { // session isn't required when using HTTP basic authentication mechanism for example if ($request->hasSession() && $request->isMethodSafe()) { $request->getSession()->set('_security.'.$this->providerKey.'.target_path', $request->getUri()); } } } PK]̗ESecurity/Http/Firewall/UsernamePasswordFormAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\HttpFoundation\Request; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\InvalidArgumentException; use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * UsernamePasswordFormAuthenticationListener is the default implementation of * an authentication via a simple form composed of a username and a password. * * @author Fabien Potencier */ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationListener { private $csrfTokenManager; /** * {@inheritdoc} */ public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, $csrfTokenManager = null) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new InvalidArgumentException('The CSRF token manager should be an instance of CsrfProviderInterface or CsrfTokenManagerInterface.'); } parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, array_merge(array( 'username_parameter' => '_username', 'password_parameter' => '_password', 'csrf_parameter' => '_csrf_token', 'intention' => 'authenticate', 'post_only' => true, ), $options), $logger, $dispatcher); $this->csrfTokenManager = $csrfTokenManager; } /** * {@inheritdoc} */ protected function requiresAuthentication(Request $request) { if ($this->options['post_only'] && !$request->isMethod('POST')) { return false; } return parent::requiresAuthentication($request); } /** * {@inheritdoc} */ protected function attemptAuthentication(Request $request) { if (null !== $this->csrfTokenManager) { $csrfToken = $request->get($this->options['csrf_parameter'], null, true); if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['intention'], $csrfToken))) { throw new InvalidCsrfTokenException('Invalid CSRF token.'); } } if ($this->options['post_only']) { $username = trim($request->request->get($this->options['username_parameter'], null, true)); $password = $request->request->get($this->options['password_parameter'], null, true); } else { $username = trim($request->get($this->options['username_parameter'], null, true)); $password = $request->get($this->options['password_parameter'], null, true); } $request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username); return $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey)); } } PK]n:Security/Http/Firewall/SimplePreAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; /** * SimplePreAuthenticationListener implements simple proxying to an authenticator. * * @author Jordi Boggiano */ class SimplePreAuthenticationListener implements ListenerInterface { private $securityContext; private $authenticationManager; private $providerKey; private $simpleAuthenticator; private $logger; /** * Constructor. * * @param SecurityContextInterface $securityContext A SecurityContext instance * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance * @param string $providerKey * @param SimplePreAuthenticatorInterface $simpleAuthenticator A SimplePreAuthenticatorInterface instance * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, SimplePreAuthenticatorInterface $simpleAuthenticator, LoggerInterface $logger = null) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->securityContext = $securityContext; $this->authenticationManager = $authenticationManager; $this->providerKey = $providerKey; $this->simpleAuthenticator = $simpleAuthenticator; $this->logger = $logger; } /** * Handles basic authentication. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (null !== $this->logger) { $this->logger->info(sprintf('Attempting simple pre-authorization %s', $this->providerKey)); } if (null !== $this->securityContext->getToken() && !$this->securityContext->getToken() instanceof AnonymousToken) { return; } try { $token = $this->simpleAuthenticator->createToken($request, $this->providerKey); $token = $this->authenticationManager->authenticate($token); $this->securityContext->setToken($token); } catch (AuthenticationException $e) { $this->securityContext->setToken(null); if (null !== $this->logger) { $this->logger->info(sprintf('Authentication request failed: %s', $e->getMessage())); } if ($this->simpleAuthenticator instanceof AuthenticationFailureHandlerInterface) { $response = $this->simpleAuthenticator->onAuthenticationFailure($request, $e); if ($response instanceof Response) { $event->setResponse($response); } elseif (null !== $response) { throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationFailure method must return null or a Response object', get_class($this->simpleAuthenticator))); } } return; } if ($this->simpleAuthenticator instanceof AuthenticationSuccessHandlerInterface) { $response = $this->simpleAuthenticator->onAuthenticationSuccess($request, $token); if ($response instanceof Response) { $event->setResponse($response); } elseif (null !== $response) { throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationSuccess method must return null or a Response object', get_class($this->simpleAuthenticator))); } } } } PK]|L@**)Security/Http/Firewall/LogoutListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Exception\InvalidArgumentException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Exception\LogoutException; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface; use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface; /** * LogoutListener logout users. * * @author Fabien Potencier */ class LogoutListener implements ListenerInterface { private $securityContext; private $options; private $handlers; private $successHandler; private $httpUtils; private $csrfTokenManager; /** * Constructor. * * @param SecurityContextInterface $securityContext * @param HttpUtils $httpUtils An HttpUtilsInterface instance * @param LogoutSuccessHandlerInterface $successHandler A LogoutSuccessHandlerInterface instance * @param array $options An array of options to process a logout attempt * @param CsrfTokenManagerInterface $csrfTokenManager A CsrfTokenManagerInterface instance */ public function __construct(SecurityContextInterface $securityContext, HttpUtils $httpUtils, LogoutSuccessHandlerInterface $successHandler, array $options = array(), $csrfTokenManager = null) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new InvalidArgumentException('The CSRF token manager should be an instance of CsrfProviderInterface or CsrfTokenManagerInterface.'); } $this->securityContext = $securityContext; $this->httpUtils = $httpUtils; $this->options = array_merge(array( 'csrf_parameter' => '_csrf_token', 'intention' => 'logout', 'logout_path' => '/logout', ), $options); $this->successHandler = $successHandler; $this->csrfTokenManager = $csrfTokenManager; $this->handlers = array(); } /** * Adds a logout handler * * @param LogoutHandlerInterface $handler */ public function addHandler(LogoutHandlerInterface $handler) { $this->handlers[] = $handler; } /** * Performs the logout if requested * * If a CsrfTokenManagerInterface instance is available, it will be used to * validate the request. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws LogoutException if the CSRF token is invalid * @throws \RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (!$this->requiresLogout($request)) { return; } if (null !== $this->csrfTokenManager) { $csrfToken = $request->get($this->options['csrf_parameter'], null, true); if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['intention'], $csrfToken))) { throw new LogoutException('Invalid CSRF token.'); } } $response = $this->successHandler->onLogoutSuccess($request); if (!$response instanceof Response) { throw new \RuntimeException('Logout Success Handler did not return a Response.'); } // handle multiple logout attempts gracefully if ($token = $this->securityContext->getToken()) { foreach ($this->handlers as $handler) { $handler->logout($request, $response, $token); } } $this->securityContext->setToken(null); $event->setResponse($response); } /** * Whether this request is asking for logout. * * The default implementation only processed requests to a specific path, * but a subclass could change this to logout requests where * certain parameters is present. * * @param Request $request * * @return Boolean */ protected function requiresLogout(Request $request) { return $this->httpUtils->checkRequestPath($request, $this->options['logout_path']); } } PK]׿ͼ 7Security/Http/Firewall/DigestAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\NonceExpiredException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\AuthenticationException; /** * DigestAuthenticationListener implements Digest HTTP authentication. * * @author Fabien Potencier */ class DigestAuthenticationListener implements ListenerInterface { private $securityContext; private $provider; private $providerKey; private $authenticationEntryPoint; private $logger; public function __construct(SecurityContextInterface $securityContext, UserProviderInterface $provider, $providerKey, DigestAuthenticationEntryPoint $authenticationEntryPoint, LoggerInterface $logger = null) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->securityContext = $securityContext; $this->provider = $provider; $this->providerKey = $providerKey; $this->authenticationEntryPoint = $authenticationEntryPoint; $this->logger = $logger; } /** * Handles digest authentication. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws AuthenticationServiceException */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (!$header = $request->server->get('PHP_AUTH_DIGEST')) { return; } $digestAuth = new DigestData($header); if (null !== $token = $this->securityContext->getToken()) { if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && $token->getUsername() === $digestAuth->getUsername()) { return; } } if (null !== $this->logger) { $this->logger->debug(sprintf('Digest Authorization header received from user agent: %s', $header)); } try { $digestAuth->validateAndDecode($this->authenticationEntryPoint->getKey(), $this->authenticationEntryPoint->getRealmName()); } catch (BadCredentialsException $e) { $this->fail($event, $request, $e); return; } try { $user = $this->provider->loadUserByUsername($digestAuth->getUsername()); if (null === $user) { throw new AuthenticationServiceException('AuthenticationDao returned null, which is an interface contract violation'); } $serverDigestMd5 = $digestAuth->calculateServerDigest($user->getPassword(), $request->getMethod()); } catch (UsernameNotFoundException $notFound) { $this->fail($event, $request, new BadCredentialsException(sprintf('Username %s not found.', $digestAuth->getUsername()))); return; } if ($serverDigestMd5 !== $digestAuth->getResponse()) { if (null !== $this->logger) { $this->logger->debug(sprintf("Expected response: '%s' but received: '%s'; is AuthenticationDao returning clear text passwords?", $serverDigestMd5, $digestAuth->getResponse())); } $this->fail($event, $request, new BadCredentialsException('Incorrect response')); return; } if ($digestAuth->isNonceExpired()) { $this->fail($event, $request, new NonceExpiredException('Nonce has expired/timed out.')); return; } if (null !== $this->logger) { $this->logger->info(sprintf('Authentication success for user "%s" with response "%s"', $digestAuth->getUsername(), $digestAuth->getResponse())); } $this->securityContext->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey)); } private function fail(GetResponseEvent $event, Request $request, AuthenticationException $authException) { $token = $this->securityContext->getToken(); if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) { $this->securityContext->setToken(null); } if (null !== $this->logger) { $this->logger->info($authException); } $event->setResponse($this->authenticationEntryPoint->start($request, $authException)); } } class DigestData { private $elements = array(); private $header; private $nonceExpiryTime; public function __construct($header) { $this->header = $header; preg_match_all('/(\w+)=("((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+))/', $header, $matches, PREG_SET_ORDER); foreach ($matches as $match) { if (isset($match[1]) && isset($match[3])) { $this->elements[$match[1]] = isset($match[4]) ? $match[4] : $match[3]; } } } public function getResponse() { return $this->elements['response']; } public function getUsername() { return strtr($this->elements['username'], array("\\\"" => "\"", "\\\\" => "\\")); } public function validateAndDecode($entryPointKey, $expectedRealm) { if ($keys = array_diff(array('username', 'realm', 'nonce', 'uri', 'response'), array_keys($this->elements))) { throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s" (%s)', $this->header, implode(', ', $keys))); } if ('auth' === $this->elements['qop']) { if (!isset($this->elements['nc']) || !isset($this->elements['cnonce'])) { throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s"', $this->header)); } } if ($expectedRealm !== $this->elements['realm']) { throw new BadCredentialsException(sprintf('Response realm name "%s" does not match system realm name of "%s".', $this->elements['realm'], $expectedRealm)); } if (false === $nonceAsPlainText = base64_decode($this->elements['nonce'])) { throw new BadCredentialsException(sprintf('Nonce is not encoded in Base64; received nonce "%s".', $this->elements['nonce'])); } $nonceTokens = explode(':', $nonceAsPlainText); if (2 !== count($nonceTokens)) { throw new BadCredentialsException(sprintf('Nonce should have yielded two tokens but was "%s".', $nonceAsPlainText)); } $this->nonceExpiryTime = $nonceTokens[0]; if (md5($this->nonceExpiryTime.':'.$entryPointKey) !== $nonceTokens[1]) { throw new BadCredentialsException(sprintf('Nonce token compromised "%s".', $nonceAsPlainText)); } } public function calculateServerDigest($password, $httpMethod) { $a2Md5 = md5(strtoupper($httpMethod).':'.$this->elements['uri']); $a1Md5 = md5($this->elements['username'].':'.$this->elements['realm'].':'.$password); $digest = $a1Md5.':'.$this->elements['nonce']; if (!isset($this->elements['qop'])) { } elseif ('auth' === $this->elements['qop']) { $digest .= ':'.$this->elements['nc'].':'.$this->elements['cnonce'].':'.$this->elements['qop']; } else { throw new \InvalidArgumentException('This method does not support a qop: "%s".', $this->elements['qop']); } $digest .= ':'.$a2Md5; return md5($digest); } public function isNonceExpired() { return $this->nonceExpiryTime < microtime(true); } } PK]~k*Security/Http/Firewall/ChannelListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Http\AccessMapInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; /** * ChannelListener switches the HTTP protocol based on the access control * configuration. * * @author Fabien Potencier */ class ChannelListener implements ListenerInterface { private $map; private $authenticationEntryPoint; private $logger; public function __construct(AccessMapInterface $map, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null) { $this->map = $map; $this->authenticationEntryPoint = $authenticationEntryPoint; $this->logger = $logger; } /** * Handles channel management. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); list($attributes, $channel) = $this->map->getPatterns($request); if ('https' === $channel && !$request->isSecure()) { if (null !== $this->logger) { $this->logger->info('Redirecting to HTTPS'); } $response = $this->authenticationEntryPoint->start($request); $event->setResponse($response); return; } if ('http' === $channel && $request->isSecure()) { if (null !== $this->logger) { $this->logger->info('Redirecting to HTTP'); } $response = $this->authenticationEntryPoint->start($request); $event->setResponse($response); } } } PK],Security/Http/Firewall/ListenerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\HttpKernel\Event\GetResponseEvent; /** * Interface that must be implemented by firewall listeners * * @author Johannes M. Schmitt */ interface ListenerInterface { /** * This interface must be implemented by firewall listeners. * * @param GetResponseEvent $event */ public function handle(GetResponseEvent $event); } PK]+/Z Z )Security/Http/Firewall/AccessListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Http\AccessMapInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; use Symfony\Component\Security\Core\Exception\AccessDeniedException; /** * AccessListener enforces access control rules. * * @author Fabien Potencier */ class AccessListener implements ListenerInterface { private $context; private $accessDecisionManager; private $map; private $authManager; public function __construct(SecurityContextInterface $context, AccessDecisionManagerInterface $accessDecisionManager, AccessMapInterface $map, AuthenticationManagerInterface $authManager) { $this->context = $context; $this->accessDecisionManager = $accessDecisionManager; $this->map = $map; $this->authManager = $authManager; } /** * Handles access authorization. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws AccessDeniedException * @throws AuthenticationCredentialsNotFoundException */ public function handle(GetResponseEvent $event) { if (null === $token = $this->context->getToken()) { throw new AuthenticationCredentialsNotFoundException('A Token was not found in the SecurityContext.'); } $request = $event->getRequest(); list($attributes, $channel) = $this->map->getPatterns($request); if (null === $attributes) { return; } if (!$token->isAuthenticated()) { $token = $this->authManager->authenticate($token); $this->context->setToken($token); } if (!$this->accessDecisionManager->decide($token, $attributes, $request)) { throw new AccessDeniedException(); } } } PK]׺=5Security/Http/Firewall/X509AuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * X509 authentication listener. * * @author Fabien Potencier */ class X509AuthenticationListener extends AbstractPreAuthenticatedListener { private $userKey; private $credentialKey; public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, $userKey = 'SSL_CLIENT_S_DN_Email', $credentialKey = 'SSL_CLIENT_S_DN', LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { parent::__construct($securityContext, $authenticationManager, $providerKey, $logger, $dispatcher); $this->userKey = $userKey; $this->credentialKey = $credentialKey; } /** * {@inheritdoc} */ protected function getPreAuthenticatedData(Request $request) { if (!$request->server->has($this->userKey)) { throw new BadCredentialsException(sprintf('SSL key was not found: %s', $this->userKey)); } return array($request->server->get($this->userKey), $request->server->get($this->credentialKey, '')); } } PK]nz+S -Security/Http/Firewall/RememberMeListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * RememberMeListener implements authentication capabilities via a cookie * * @author Johannes M. Schmitt */ class RememberMeListener implements ListenerInterface { private $securityContext; private $rememberMeServices; private $authenticationManager; private $logger; private $dispatcher; /** * Constructor. * * @param SecurityContextInterface $securityContext * @param RememberMeServicesInterface $rememberMeServices * @param AuthenticationManagerInterface $authenticationManager * @param LoggerInterface $logger * @param EventDispatcherInterface $dispatcher */ public function __construct(SecurityContextInterface $securityContext, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { $this->securityContext = $securityContext; $this->rememberMeServices = $rememberMeServices; $this->authenticationManager = $authenticationManager; $this->logger = $logger; $this->dispatcher = $dispatcher; } /** * Handles remember-me cookie based authentication. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { if (null !== $this->securityContext->getToken()) { return; } $request = $event->getRequest(); if (null === $token = $this->rememberMeServices->autoLogin($request)) { return; } try { $token = $this->authenticationManager->authenticate($token); $this->securityContext->setToken($token); if (null !== $this->dispatcher) { $loginEvent = new InteractiveLoginEvent($request, $token); $this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent); } if (null !== $this->logger) { $this->logger->debug('SecurityContext populated with remember-me token.'); } } catch (AuthenticationException $failed) { if (null !== $this->logger) { $this->logger->warning( 'SecurityContext not populated with remember-me token as the' .' AuthenticationManager rejected the AuthenticationToken returned' .' by the RememberMeServices: '.$failed->getMessage() ); } $this->rememberMeServices->loginFail($request); } } } PK]lٯ:Security/Http/Firewall/AnonymousAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; /** * AnonymousAuthenticationListener automatically adds a Token if none is * already present. * * @author Fabien Potencier */ class AnonymousAuthenticationListener implements ListenerInterface { private $context; private $key; private $logger; public function __construct(SecurityContextInterface $context, $key, LoggerInterface $logger = null) { $this->context = $context; $this->key = $key; $this->logger = $logger; } /** * Handles anonymous authentication. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { if (null !== $this->context->getToken()) { return; } $this->context->setToken(new AnonymousToken($this->key, 'anon.', array())); if (null !== $this->logger) { $this->logger->info('Populated SecurityContext with an anonymous Token'); } } } PK]^V<Security/Http/Authorization/AccessDeniedHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authorization; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Exception\AccessDeniedException; /** * This is used by the ExceptionListener to translate an AccessDeniedException * to a Response object. * * @author Johannes M. Schmitt */ interface AccessDeniedHandlerInterface { /** * Handles an access denied failure. * * @param Request $request * @param AccessDeniedException $accessDeniedException * * @return Response may return null */ public function handle(Request $request, AccessDeniedException $accessDeniedException); } PK]a$9Security/Http/RememberMe/TokenBasedRememberMeServices.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\RememberMe; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\User\UserInterface; /** * Concrete implementation of the RememberMeServicesInterface providing * remember-me capabilities without requiring a TokenProvider. * * @author Johannes M. Schmitt */ class TokenBasedRememberMeServices extends AbstractRememberMeServices { /** * {@inheritDoc} */ protected function processAutoLoginCookie(array $cookieParts, Request $request) { if (count($cookieParts) !== 4) { throw new AuthenticationException('The cookie is invalid.'); } list($class, $username, $expires, $hash) = $cookieParts; if (false === $username = base64_decode($username, true)) { throw new AuthenticationException('$username contains a character from outside the base64 alphabet.'); } try { $user = $this->getUserProvider($class)->loadUserByUsername($username); } catch (\Exception $ex) { if (!$ex instanceof AuthenticationException) { $ex = new AuthenticationException($ex->getMessage(), $ex->getCode(), $ex); } throw $ex; } if (!$user instanceof UserInterface) { throw new \RuntimeException(sprintf('The UserProviderInterface implementation must return an instance of UserInterface, but returned "%s".', get_class($user))); } if (true !== $this->compareHashes($hash, $this->generateCookieHash($class, $username, $expires, $user->getPassword()))) { throw new AuthenticationException('The cookie\'s hash is invalid.'); } if ($expires < time()) { throw new AuthenticationException('The cookie has expired.'); } return $user; } /** * Compares two hashes using a constant-time algorithm to avoid (remote) * timing attacks. * * This is the same implementation as used in the BasePasswordEncoder. * * @param string $hash1 The first hash * @param string $hash2 The second hash * * @return Boolean true if the two hashes are the same, false otherwise */ private function compareHashes($hash1, $hash2) { if (strlen($hash1) !== $c = strlen($hash2)) { return false; } $result = 0; for ($i = 0; $i < $c; $i++) { $result |= ord($hash1[$i]) ^ ord($hash2[$i]); } return 0 === $result; } /** * {@inheritDoc} */ protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token) { $user = $token->getUser(); $expires = time() + $this->options['lifetime']; $value = $this->generateCookieValue(get_class($user), $user->getUsername(), $expires, $user->getPassword()); $response->headers->setCookie( new Cookie( $this->options['name'], $value, $expires, $this->options['path'], $this->options['domain'], $this->options['secure'], $this->options['httponly'] ) ); } /** * Generates the cookie value. * * @param string $class * @param string $username The username * @param integer $expires The Unix timestamp when the cookie expires * @param string $password The encoded password * * @throws \RuntimeException if username contains invalid chars * * @return string */ protected function generateCookieValue($class, $username, $expires, $password) { return $this->encodeCookie(array( $class, base64_encode($username), $expires, $this->generateCookieHash($class, $username, $expires, $password) )); } /** * Generates a hash for the cookie to ensure it is not being tempered with * * @param string $class * @param string $username The username * @param integer $expires The Unix timestamp when the cookie expires * @param string $password The encoded password * * @throws \RuntimeException when the private key is empty * * @return string */ protected function generateCookieHash($class, $username, $expires, $password) { return hash_hmac('sha256', $class.$username.$expires.$password, $this->getKey()); } } PK]*b&&7Security/Http/RememberMe/AbstractRememberMeServices.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\RememberMe; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\CookieTheftException; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Cookie; use Psr\Log\LoggerInterface; /** * Base class implementing the RememberMeServicesInterface * * @author Johannes M. Schmitt */ abstract class AbstractRememberMeServices implements RememberMeServicesInterface, LogoutHandlerInterface { const COOKIE_DELIMITER = ':'; protected $logger; protected $options; private $providerKey; private $key; private $userProviders; /** * Constructor. * * @param array $userProviders * @param string $key * @param string $providerKey * @param array $options * @param LoggerInterface $logger * * @throws \InvalidArgumentException */ public function __construct(array $userProviders, $key, $providerKey, array $options = array(), LoggerInterface $logger = null) { if (empty($key)) { throw new \InvalidArgumentException('$key must not be empty.'); } if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } if (0 === count($userProviders)) { throw new \InvalidArgumentException('You must provide at least one user provider.'); } $this->userProviders = $userProviders; $this->key = $key; $this->providerKey = $providerKey; $this->options = $options; $this->logger = $logger; } /** * Returns the parameter that is used for checking whether remember-me * services have been requested. * * @return string */ public function getRememberMeParameter() { return $this->options['remember_me_parameter']; } /** * @return string */ public function getKey() { return $this->key; } /** * Implementation of RememberMeServicesInterface. Detects whether a remember-me * cookie was set, decodes it, and hands it to subclasses for further processing. * * @param Request $request * * @return TokenInterface|null * * @throws CookieTheftException * @throws \RuntimeException */ final public function autoLogin(Request $request) { if (null === $cookie = $request->cookies->get($this->options['name'])) { return; } if (null !== $this->logger) { $this->logger->debug('Remember-me cookie detected.'); } $cookieParts = $this->decodeCookie($cookie); try { $user = $this->processAutoLoginCookie($cookieParts, $request); if (!$user instanceof UserInterface) { throw new \RuntimeException('processAutoLoginCookie() must return a UserInterface implementation.'); } if (null !== $this->logger) { $this->logger->info('Remember-me cookie accepted.'); } return new RememberMeToken($user, $this->providerKey, $this->key); } catch (CookieTheftException $theft) { $this->cancelCookie($request); throw $theft; } catch (UsernameNotFoundException $notFound) { if (null !== $this->logger) { $this->logger->info('User for remember-me cookie not found.'); } } catch (UnsupportedUserException $unSupported) { if (null !== $this->logger) { $this->logger->warning('User class for remember-me cookie not supported.'); } } catch (AuthenticationException $invalid) { if (null !== $this->logger) { $this->logger->debug('Remember-Me authentication failed: '.$invalid->getMessage()); } } $this->cancelCookie($request); return null; } /** * Implementation for LogoutHandlerInterface. Deletes the cookie. * * @param Request $request * @param Response $response * @param TokenInterface $token */ public function logout(Request $request, Response $response, TokenInterface $token) { $this->cancelCookie($request); } /** * Implementation for RememberMeServicesInterface. Deletes the cookie when * an attempted authentication fails. * * @param Request $request */ final public function loginFail(Request $request) { $this->cancelCookie($request); $this->onLoginFail($request); } /** * Implementation for RememberMeServicesInterface. This is called when an * authentication is successful. * * @param Request $request * @param Response $response * @param TokenInterface $token The token that resulted in a successful authentication */ final public function loginSuccess(Request $request, Response $response, TokenInterface $token) { // Make sure any old remember-me cookies are cancelled $this->cancelCookie($request); if (!$token->getUser() instanceof UserInterface) { if (null !== $this->logger) { $this->logger->debug('Remember-me ignores token since it does not contain a UserInterface implementation.'); } return; } if (!$this->isRememberMeRequested($request)) { if (null !== $this->logger) { $this->logger->debug('Remember-me was not requested.'); } return; } if (null !== $this->logger) { $this->logger->debug('Remember-me was requested; setting cookie.'); } // Remove attribute from request that sets a NULL cookie. // It was set by $this->cancelCookie() // (cancelCookie does other things too for some RememberMeServices // so we should still call it at the start of this method) $request->attributes->remove(self::COOKIE_ATTR_NAME); $this->onLoginSuccess($request, $response, $token); } /** * Subclasses should validate the cookie and do any additional processing * that is required. This is called from autoLogin(). * * @param array $cookieParts * @param Request $request * * @return TokenInterface */ abstract protected function processAutoLoginCookie(array $cookieParts, Request $request); /** * @param Request $request */ protected function onLoginFail(Request $request) { } /** * This is called after a user has been logged in successfully, and has * requested remember-me capabilities. The implementation usually sets a * cookie and possibly stores a persistent record of it. * * @param Request $request * @param Response $response * @param TokenInterface $token */ abstract protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token); final protected function getUserProvider($class) { foreach ($this->userProviders as $provider) { if ($provider->supportsClass($class)) { return $provider; } } throw new UnsupportedUserException(sprintf('There is no user provider that supports class "%s".', $class)); } /** * Decodes the raw cookie value * * @param string $rawCookie * * @return array */ protected function decodeCookie($rawCookie) { return explode(self::COOKIE_DELIMITER, base64_decode($rawCookie)); } /** * Encodes the cookie parts * * @param array $cookieParts * * @return string */ protected function encodeCookie(array $cookieParts) { return base64_encode(implode(self::COOKIE_DELIMITER, $cookieParts)); } /** * Deletes the remember-me cookie * * @param Request $request */ protected function cancelCookie(Request $request) { if (null !== $this->logger) { $this->logger->debug(sprintf('Clearing remember-me cookie "%s"', $this->options['name'])); } $request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie($this->options['name'], null, 1, $this->options['path'], $this->options['domain'])); } /** * Checks whether remember-me capabilities were requested * * @param Request $request * * @return Boolean */ protected function isRememberMeRequested(Request $request) { if (true === $this->options['always_remember_me']) { return true; } $parameter = $request->get($this->options['remember_me_parameter'], null, true); if ($parameter === null && null !== $this->logger) { $this->logger->debug(sprintf('Did not send remember-me cookie (remember-me parameter "%s" was not sent).', $this->options['remember_me_parameter'])); } return $parameter === 'true' || $parameter === 'on' || $parameter === '1' || $parameter === 'yes'; } } PK]Pڕ-Security/Http/RememberMe/ResponseListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\RememberMe; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Adds remember-me cookies to the Response. * * @author Johannes M. Schmitt */ class ResponseListener implements EventSubscriberInterface { /** * @param FilterResponseEvent $event */ public function onKernelResponse(FilterResponseEvent $event) { $request = $event->getRequest(); $response = $event->getResponse(); if ($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)) { $response->headers->setCookie($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)); } } /** * {@inheritDoc} */ public static function getSubscribedEvents() { return array(KernelEvents::RESPONSE => 'onKernelResponse'); } } PK]s44CSecurity/Http/RememberMe/PersistentTokenBasedRememberMeServices.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\RememberMe; use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\CookieTheftException; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Util\SecureRandomInterface; use Psr\Log\LoggerInterface; /** * Concrete implementation of the RememberMeServicesInterface which needs * an implementation of TokenProviderInterface for providing remember-me * capabilities. * * @author Johannes M. Schmitt */ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices { private $tokenProvider; private $secureRandom; /** * Constructor. * * @param array $userProviders * @param string $key * @param string $providerKey * @param array $options * @param LoggerInterface $logger * @param SecureRandomInterface $secureRandom */ public function __construct(array $userProviders, $key, $providerKey, array $options = array(), LoggerInterface $logger = null, SecureRandomInterface $secureRandom) { parent::__construct($userProviders, $key, $providerKey, $options, $logger); $this->secureRandom = $secureRandom; } /** * Sets the token provider * * @param TokenProviderInterface $tokenProvider */ public function setTokenProvider(TokenProviderInterface $tokenProvider) { $this->tokenProvider = $tokenProvider; } /** * {@inheritDoc} */ protected function cancelCookie(Request $request) { // Delete cookie on the client parent::cancelCookie($request); // Delete cookie from the tokenProvider if (null !== ($cookie = $request->cookies->get($this->options['name'])) && count($parts = $this->decodeCookie($cookie)) === 2 ) { list($series, $tokenValue) = $parts; $this->tokenProvider->deleteTokenBySeries($series); } } /** * {@inheritDoc} */ protected function processAutoLoginCookie(array $cookieParts, Request $request) { if (count($cookieParts) !== 2) { throw new AuthenticationException('The cookie is invalid.'); } list($series, $tokenValue) = $cookieParts; $persistentToken = $this->tokenProvider->loadTokenBySeries($series); if ($persistentToken->getTokenValue() !== $tokenValue) { throw new CookieTheftException('This token was already used. The account is possibly compromised.'); } if ($persistentToken->getLastUsed()->getTimestamp() + $this->options['lifetime'] < time()) { throw new AuthenticationException('The cookie has expired.'); } $series = $persistentToken->getSeries(); $tokenValue = base64_encode($this->secureRandom->nextBytes(64)); $this->tokenProvider->updateToken($series, $tokenValue, new \DateTime()); $request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie( $this->options['name'], $this->encodeCookie(array($series, $tokenValue)), time() + $this->options['lifetime'], $this->options['path'], $this->options['domain'], $this->options['secure'], $this->options['httponly'] ) ); return $this->getUserProvider($persistentToken->getClass())->loadUserByUsername($persistentToken->getUsername()); } /** * {@inheritDoc} */ protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token) { $series = base64_encode($this->secureRandom->nextBytes(64)); $tokenValue = base64_encode($this->secureRandom->nextBytes(64)); $this->tokenProvider->createNewToken( new PersistentToken( get_class($user = $token->getUser()), $user->getUsername(), $series, $tokenValue, new \DateTime() ) ); $response->headers->setCookie( new Cookie( $this->options['name'], $this->encodeCookie(array($series, $tokenValue)), time() + $this->options['lifetime'], $this->options['path'], $this->options['domain'], $this->options['secure'], $this->options['httponly'] ) ); } } PK] z 8Security/Http/RememberMe/RememberMeServicesInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Interface that needs to be implemented by classes which provide remember-me * capabilities. * * We provide two implementations out-of-the-box: * - TokenBasedRememberMeServices (does not require a TokenProvider) * - PersistentTokenBasedRememberMeServices (requires a TokenProvider) * * @author Johannes M. Schmitt */ interface RememberMeServicesInterface { /** * This attribute name can be used by the implementation if it needs to set * a cookie on the Request when there is no actual Response, yet. * * @var string */ const COOKIE_ATTR_NAME = '_security_remember_me_cookie'; /** * This method will be called whenever the SecurityContext does not contain * an TokenInterface object and the framework wishes to provide an implementation * with an opportunity to authenticate the request using remember-me capabilities. * * No attempt whatsoever is made to determine whether the browser has requested * remember-me services or presented a valid cookie. Any and all such determinations * are left to the implementation of this method. * * If a browser has presented an unauthorised cookie for whatever reason, * make sure to throw an AuthenticationException as this will consequentially * result in a call to loginFail() and therefore an invalidation of the cookie. * * @param Request $request * * @return TokenInterface */ public function autoLogin(Request $request); /** * Called whenever an interactive authentication attempt was made, but the * credentials supplied by the user were missing or otherwise invalid. * * This method needs to take care of invalidating the cookie. * * @param Request $request */ public function loginFail(Request $request); /** * Called whenever an interactive authentication attempt is successful * (e.g. a form login). * * An implementation may always set a remember-me cookie in the Response, * although this is not recommended. * * Instead, implementations should typically look for a request parameter * (such as a HTTP POST parameter) that indicates the browser has explicitly * requested for the authentication to be remembered. * * @param Request $request * @param Response $response * @param TokenInterface $token */ public function loginSuccess(Request $request, Response $response, TokenInterface $token); } PK]2jSecurity/Http/AccessMap.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\HttpFoundation\RequestMatcherInterface; use Symfony\Component\HttpFoundation\Request; /** * AccessMap allows configuration of different access control rules for * specific parts of the website. * * @author Fabien Potencier */ class AccessMap implements AccessMapInterface { private $map = array(); /** * Constructor. * * @param RequestMatcherInterface $requestMatcher A RequestMatcherInterface instance * @param array $attributes An array of attributes to pass to the access decision manager (like roles) * @param string|null $channel The channel to enforce (http, https, or null) */ public function add(RequestMatcherInterface $requestMatcher, array $attributes = array(), $channel = null) { $this->map[] = array($requestMatcher, $attributes, $channel); } /** * {@inheritDoc} */ public function getPatterns(Request $request) { foreach ($this->map as $elements) { if (null === $elements[0] || $elements[0]->matches($request)) { return array($elements[1], $elements[2]); } } return array(null, null); } } PK]`CSecurity/Http/HttpUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; /** * Encapsulates the logic needed to create sub-requests, redirect the user, and match URLs. * * @author Fabien Potencier */ class HttpUtils { private $urlGenerator; private $urlMatcher; /** * Constructor. * * @param UrlGeneratorInterface $urlGenerator A UrlGeneratorInterface instance * @param UrlMatcherInterface|RequestMatcherInterface $urlMatcher The URL or Request matcher * * @throws \InvalidArgumentException */ public function __construct(UrlGeneratorInterface $urlGenerator = null, $urlMatcher = null) { $this->urlGenerator = $urlGenerator; if ($urlMatcher !== null && !$urlMatcher instanceof UrlMatcherInterface && !$urlMatcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); } $this->urlMatcher = $urlMatcher; } /** * Creates a redirect Response. * * @param Request $request A Request instance * @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo)) * @param integer $status The status code * * @return RedirectResponse A RedirectResponse instance */ public function createRedirectResponse(Request $request, $path, $status = 302) { return new RedirectResponse($this->generateUri($request, $path), $status); } /** * Creates a Request. * * @param Request $request The current Request instance * @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo)) * * @return Request A Request instance */ public function createRequest(Request $request, $path) { $newRequest = Request::create($this->generateUri($request, $path), 'get', array(), $request->cookies->all(), array(), $request->server->all()); if ($request->hasSession()) { $newRequest->setSession($request->getSession()); } if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) { $newRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $request->attributes->get(SecurityContextInterface::AUTHENTICATION_ERROR)); } if ($request->attributes->has(SecurityContextInterface::ACCESS_DENIED_ERROR)) { $newRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $request->attributes->get(SecurityContextInterface::ACCESS_DENIED_ERROR)); } if ($request->attributes->has(SecurityContextInterface::LAST_USERNAME)) { $newRequest->attributes->set(SecurityContextInterface::LAST_USERNAME, $request->attributes->get(SecurityContextInterface::LAST_USERNAME)); } return $newRequest; } /** * Checks that a given path matches the Request. * * @param Request $request A Request instance * @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo)) * * @return Boolean true if the path is the same as the one from the Request, false otherwise */ public function checkRequestPath(Request $request, $path) { if ('/' !== $path[0]) { try { // matching a request is more powerful than matching a URL path + context, so try that first if ($this->urlMatcher instanceof RequestMatcherInterface) { $parameters = $this->urlMatcher->matchRequest($request); } else { $parameters = $this->urlMatcher->match($request->getPathInfo()); } return $path === $parameters['_route']; } catch (MethodNotAllowedException $e) { return false; } catch (ResourceNotFoundException $e) { return false; } } return $path === rawurldecode($request->getPathInfo()); } /** * Generates a URI, based on the given path or absolute URL. * * @param Request $request A Request instance * @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo)) * * @return string An absolute URL * * @throws \LogicException */ public function generateUri($request, $path) { if (0 === strpos($path, 'http') || !$path) { return $path; } if ('/' === $path[0]) { return $request->getUriForPath($path); } if (null === $this->urlGenerator) { throw new \LogicException('You must provide a UrlGeneratorInterface instance to be able to use routes.'); } $url = $this->urlGenerator->generate($path, $request->attributes->all(), UrlGeneratorInterface::ABSOLUTE_URL); // unnecessary query string parameters must be removed from URL // (ie. query parameters that are presents in $attributes) // fortunately, they all are, so we have to remove entire query string $position = strpos($url, '?'); if (false !== $position) { $url = substr($url, 0, $position); } return $url; } } PK]/ sG Security/Http/SecurityEvents.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; final class SecurityEvents { /** * The INTERACTIVE_LOGIN event occurs after a user is logged in * interactively for authentication based on http, cookies or X509. * * The event listener method receives a * Symfony\Component\Security\Http\Event\InteractiveLoginEvent instance. * * @var string */ const INTERACTIVE_LOGIN = 'security.interactive_login'; /** * The SWITCH_USER event occurs before switch to another user and * before exit from an already switched user. * * The event listener method receives a * Symfony\Component\Security\Http\Event\SwitchUserEvent instance. * * @var string */ const SWITCH_USER = 'security.switch_user'; } PK]D'Security/Http/Event/SwitchUserEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\EventDispatcher\Event; /** * SwitchUserEvent * * @author Fabien Potencier */ class SwitchUserEvent extends Event { private $request; private $targetUser; public function __construct(Request $request, UserInterface $targetUser) { $this->request = $request; $this->targetUser = $targetUser; } /** * @return Request */ public function getRequest() { return $this->request; } /** * @return UserInterface */ public function getTargetUser() { return $this->targetUser; } } PK]Zv}-Security/Http/Event/InteractiveLoginEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * InteractiveLoginEvent * * @author Fabien Potencier */ class InteractiveLoginEvent extends Event { private $request; private $authenticationToken; /** * Constructor. * * @param Request $request A Request instance * @param TokenInterface $authenticationToken A TokenInterface instance */ public function __construct(Request $request, TokenInterface $authenticationToken) { $this->request = $request; $this->authenticationToken = $authenticationToken; } /** * Gets the request. * * @return Request A Request instance */ public function getRequest() { return $this->request; } /** * Gets the authentication token. * * @return TokenInterface A TokenInterface instance */ public function getAuthenticationToken() { return $this->authenticationToken; } } PK]H]  FSecurity/Http/Authentication/AuthenticationFailureHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authentication; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Interface for custom authentication failure handlers. * * If you want to customize the failure handling process, instead of * overwriting the respective listener globally, you can set a custom failure * handler which implements this interface. * * @author Johannes M. Schmitt */ interface AuthenticationFailureHandlerInterface { /** * This is called when an interactive authentication attempt fails. This is * called by authentication listeners inheriting from * AbstractAuthenticationListener. * * @param Request $request * @param AuthenticationException $exception * * @return Response The response to return, never null */ public function onAuthenticationFailure(Request $request, AuthenticationException $exception); } PK]AH\ݞ<Security/Http/Authentication/SimpleAuthenticationHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authentication; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface; /** * Class to proxy authentication success/failure handlers * * Events are sent to the SimpleAuthenticatorInterface if it implements * the right interface, otherwise (or if it fails to return a Response) * the default handlers are triggered. * * @author Jordi Boggiano */ class SimpleAuthenticationHandler implements AuthenticationFailureHandlerInterface, AuthenticationSuccessHandlerInterface { protected $successHandler; protected $failureHandler; protected $simpleAuthenticator; protected $logger; /** * Constructor. * * @param SimpleAuthenticatorInterface $authenticator SimpleAuthenticatorInterface instance * @param AuthenticationSuccessHandlerInterface $successHandler Default success handler * @param AuthenticationFailureHandlerInterface $failureHandler Default failure handler * @param LoggerInterface $logger Optional logger */ public function __construct(SimpleAuthenticatorInterface $authenticator, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, LoggerInterface $logger = null) { $this->simpleAuthenticator = $authenticator; $this->successHandler = $successHandler; $this->failureHandler = $failureHandler; $this->logger = $logger; } /** * {@inheritDoc} */ public function onAuthenticationSuccess(Request $request, TokenInterface $token) { if ($this->simpleAuthenticator instanceof AuthenticationSuccessHandlerInterface) { if ($this->logger) { $this->logger->debug(sprintf('Using the %s object as authentication success handler', get_class($this->simpleAuthenticator))); } $response = $this->simpleAuthenticator->onAuthenticationSuccess($request, $token); if ($response instanceof Response) { return $response; } if (null !== $response) { throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationSuccess method must return null to use the default success handler, or a Response object', get_class($this->simpleAuthenticator))); } } if ($this->logger) { $this->logger->debug('Fallback to the default authentication success handler'); } return $this->successHandler->onAuthenticationSuccess($request, $token); } /** * {@inheritDoc} */ public function onAuthenticationFailure(Request $request, AuthenticationException $exception) { if ($this->simpleAuthenticator instanceof AuthenticationFailureHandlerInterface) { if ($this->logger) { $this->logger->debug(sprintf('Using the %s object as authentication failure handler', get_class($this->simpleAuthenticator))); } $response = $this->simpleAuthenticator->onAuthenticationFailure($request, $exception); if ($response instanceof Response) { return $response; } if (null !== $response) { throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationFailure method must return null to use the default failure handler, or a Response object', get_class($this->simpleAuthenticator))); } } if ($this->logger) { $this->logger->debug('Fallback to the default authentication failure handler'); } return $this->failureHandler->onAuthenticationFailure($request, $exception); } } PK]NAFSecurity/Http/Authentication/AuthenticationSuccessHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Interface for a custom authentication success handler * * If you want to customize the success handling process, instead of * overwriting the respective listener globally, you can set a custom success * handler which implements this interface. * * @author Johannes M. Schmitt */ interface AuthenticationSuccessHandlerInterface { /** * This is called when an interactive authentication attempt succeeds. This * is called by authentication listeners inheriting from * AbstractAuthenticationListener. * * @param Request $request * @param TokenInterface $token * * @return Response never null */ public function onAuthenticationSuccess(Request $request, TokenInterface $token); } PK] DSecurity/Http/Authentication/DefaultAuthenticationFailureHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authentication; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Http\HttpUtils; /** * Class with the default authentication failure handling logic. * * Can be optionally be extended from by the developer to alter the behaviour * while keeping the default behaviour. * * @author Fabien Potencier * @author Johannes M. Schmitt * @author Alexander */ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandlerInterface { protected $httpKernel; protected $httpUtils; protected $logger; protected $options; /** * Constructor. * * @param HttpKernelInterface $httpKernel * @param HttpUtils $httpUtils * @param array $options Options for processing a failed authentication attempt. * @param LoggerInterface $logger Optional logger */ public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options, LoggerInterface $logger = null) { $this->httpKernel = $httpKernel; $this->httpUtils = $httpUtils; $this->logger = $logger; $this->options = array_merge(array( 'failure_path' => null, 'failure_forward' => false, 'login_path' => '/login', 'failure_path_parameter' => '_failure_path' ), $options); } /** * {@inheritDoc} */ public function onAuthenticationFailure(Request $request, AuthenticationException $exception) { if ($failureUrl = $request->get($this->options['failure_path_parameter'], null, true)) { $this->options['failure_path'] = $failureUrl; } if (null === $this->options['failure_path']) { $this->options['failure_path'] = $this->options['login_path']; } if ($this->options['failure_forward']) { if (null !== $this->logger) { $this->logger->debug(sprintf('Forwarding to %s', $this->options['failure_path'])); } $subRequest = $this->httpUtils->createRequest($request, $this->options['failure_path']); $subRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception); return $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST); } if (null !== $this->logger) { $this->logger->debug(sprintf('Redirecting to %s', $this->options['failure_path'])); } $request->getSession()->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception); return $this->httpUtils->createRedirectResponse($request, $this->options['failure_path']); } } PK]xGA A DSecurity/Http/Authentication/DefaultAuthenticationSuccessHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Http\HttpUtils; /** * Class with the default authentication success handling logic. * * @author Fabien Potencier * @author Johannes M. Schmitt * @author Alexander */ class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface { protected $httpUtils; protected $options; protected $providerKey; /** * Constructor. * * @param HttpUtils $httpUtils * @param array $options Options for processing a successful authentication attempt. */ public function __construct(HttpUtils $httpUtils, array $options) { $this->httpUtils = $httpUtils; $this->options = array_merge(array( 'always_use_default_target_path' => false, 'default_target_path' => '/', 'login_path' => '/login', 'target_path_parameter' => '_target_path', 'use_referer' => false, ), $options); } /** * {@inheritDoc} */ public function onAuthenticationSuccess(Request $request, TokenInterface $token) { return $this->httpUtils->createRedirectResponse($request, $this->determineTargetUrl($request)); } /** * Get the provider key. * * @return string */ public function getProviderKey() { return $this->providerKey; } /** * Set the provider key. * * @param string $providerKey */ public function setProviderKey($providerKey) { $this->providerKey = $providerKey; } /** * Builds the target URL according to the defined options. * * @param Request $request * * @return string */ protected function determineTargetUrl(Request $request) { if ($this->options['always_use_default_target_path']) { return $this->options['default_target_path']; } if ($targetUrl = $request->get($this->options['target_path_parameter'], null, true)) { return $targetUrl; } if (null !== $this->providerKey && $targetUrl = $request->getSession()->get('_security.'.$this->providerKey.'.target_path')) { $request->getSession()->remove('_security.'.$this->providerKey.'.target_path'); return $targetUrl; } if ($this->options['use_referer'] && ($targetUrl = $request->headers->get('Referer')) && $targetUrl !== $this->httpUtils->generateUri($request, $this->options['login_path'])) { return $targetUrl; } return $this->options['default_target_path']; } } PK]6O/Security/Http/Logout/LogoutHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Logout; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; /** * Interface that needs to be implemented by LogoutHandlers. * * @author Johannes M. Schmitt */ interface LogoutHandlerInterface { /** * This method is called by the LogoutListener when a user has requested * to be logged out. Usually, you would unset session variables, or remove * cookies, etc. * * @param Request $request * @param Response $response * @param TokenInterface $token */ public function logout(Request $request, Response $response, TokenInterface $token); } PK]\ü-Security/Http/Logout/SessionLogoutHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Logout; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; /** * Handler for clearing invalidating the current session. * * @author Johannes M. Schmitt */ class SessionLogoutHandler implements LogoutHandlerInterface { /** * Invalidate the current session * * @param Request $request * @param Response $response * @param TokenInterface $token */ public function logout(Request $request, Response $response, TokenInterface $token) { $request->getSession()->invalidate(); } } PK]dd4Security/Http/Logout/CookieClearingLogoutHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Logout; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; /** * This handler clears the passed cookies when a user logs out. * * @author Johannes M. Schmitt */ class CookieClearingLogoutHandler implements LogoutHandlerInterface { private $cookies; /** * Constructor. * * @param array $cookies An array of cookie names to unset */ public function __construct(array $cookies) { $this->cookies = $cookies; } /** * Implementation for the LogoutHandlerInterface. Deletes all requested cookies. * * @param Request $request * @param Response $response * @param TokenInterface $token */ public function logout(Request $request, Response $response, TokenInterface $token) { foreach ($this->cookies as $cookieName => $cookieData) { $response->headers->clearCookie($cookieName, $cookieData['path'], $cookieData['domain']); } } } PK]a7ll4Security/Http/Logout/DefaultLogoutSuccessHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Logout; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Http\HttpUtils; /** * Default logout success handler will redirect users to a configured path. * * @author Fabien Potencier * @author Alexander */ class DefaultLogoutSuccessHandler implements LogoutSuccessHandlerInterface { protected $httpUtils; protected $targetUrl; /** * @param HttpUtils $httpUtils * @param string $targetUrl */ public function __construct(HttpUtils $httpUtils, $targetUrl = '/') { $this->httpUtils = $httpUtils; $this->targetUrl = $targetUrl; } /** * {@inheritDoc} */ public function onLogoutSuccess(Request $request) { return $this->httpUtils->createRedirectResponse($request, $this->targetUrl); } } PK]1d6Security/Http/Logout/LogoutSuccessHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Logout; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * LogoutSuccesshandlerInterface. * * In contrast to the LogoutHandlerInterface, this interface can return a response * which is then used instead of the default behavior. * * If you want to only perform some logout related clean-up task, use the * LogoutHandlerInterface instead. * * @author Johannes M. Schmitt */ interface LogoutSuccessHandlerInterface { /** * Creates a Response object to send upon a successful logout. * * @param Request $request * * @return Response never null */ public function onLogoutSuccess(Request $request); } PK]/``$Security/Http/AccessMapInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\HttpFoundation\Request; /** * AccessMap allows configuration of different access control rules for * specific parts of the website. * * @author Fabien Potencier * @author Kris Wallsmith */ interface AccessMapInterface { /** * Returns security attributes and required channel for the supplied request. * * @param Request $request The current request * * @return array A tuple of security attributes and the required channel */ public function getPatterns(Request $request); } PK]DXV V Security/Http/Firewall.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Firewall uses a FirewallMap to register security listeners for the given * request. * * It allows for different security strategies within the same application * (a Basic authentication for the /api, and a web based authentication for * everything else for instance). * * @author Fabien Potencier */ class Firewall implements EventSubscriberInterface { private $map; private $dispatcher; private $exceptionListeners; /** * Constructor. * * @param FirewallMapInterface $map A FirewallMapInterface instance * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance */ public function __construct(FirewallMapInterface $map, EventDispatcherInterface $dispatcher) { $this->map = $map; $this->dispatcher = $dispatcher; $this->exceptionListeners = new \SplObjectStorage(); } /** * Handles security. * * @param GetResponseEvent $event An GetResponseEvent instance */ public function onKernelRequest(GetResponseEvent $event) { if (!$event->isMasterRequest()) { return; } // register listeners for this firewall list($listeners, $exceptionListener) = $this->map->getListeners($event->getRequest()); if (null !== $exceptionListener) { $this->exceptionListeners[$event->getRequest()] = $exceptionListener; $exceptionListener->register($this->dispatcher); } // initiate the listener chain foreach ($listeners as $listener) { $listener->handle($event); if ($event->hasResponse()) { break; } } } public function onKernelFinishRequest(FinishRequestEvent $event) { $request = $event->getRequest(); if (isset($this->exceptionListeners[$request])) { $this->exceptionListeners[$request]->unregister($this->dispatcher); unset($this->exceptionListeners[$request]); } } /** * {@inheritDoc} */ public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array('onKernelRequest', 8), KernelEvents::FINISH_REQUEST => 'onKernelFinishRequest', ); } } PK]י9Security/Http/EntryPoint/FormAuthenticationEntryPoint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\EntryPoint; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * FormAuthenticationEntryPoint starts an authentication via a login form. * * @author Fabien Potencier */ class FormAuthenticationEntryPoint implements AuthenticationEntryPointInterface { private $loginPath; private $useForward; private $httpKernel; private $httpUtils; /** * Constructor. * * @param HttpKernelInterface $kernel * @param HttpUtils $httpUtils An HttpUtils instance * @param string $loginPath The path to the login form * @param Boolean $useForward Whether to forward or redirect to the login form */ public function __construct(HttpKernelInterface $kernel, HttpUtils $httpUtils, $loginPath, $useForward = false) { $this->httpKernel = $kernel; $this->httpUtils = $httpUtils; $this->loginPath = $loginPath; $this->useForward = (Boolean) $useForward; } /** * {@inheritdoc} */ public function start(Request $request, AuthenticationException $authException = null) { if ($this->useForward) { $subRequest = $this->httpUtils->createRequest($request, $this->loginPath); $response = $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST); if (200 === $response->getStatusCode()) { $response->headers->set('X-Status-Code', 401); } return $response; } return $this->httpUtils->createRedirectResponse($request, $this->loginPath); } } PK]tZ)K K ;Security/Http/EntryPoint/DigestAuthenticationEntryPoint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\EntryPoint; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\NonceExpiredException; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Psr\Log\LoggerInterface; /** * DigestAuthenticationEntryPoint starts an HTTP Digest authentication. * * @author Fabien Potencier */ class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterface { private $key; private $realmName; private $nonceValiditySeconds; private $logger; public function __construct($realmName, $key, $nonceValiditySeconds = 300, LoggerInterface $logger = null) { $this->realmName = $realmName; $this->key = $key; $this->nonceValiditySeconds = $nonceValiditySeconds; $this->logger = $logger; } /** * {@inheritdoc} */ public function start(Request $request, AuthenticationException $authException = null) { $expiryTime = microtime(true) + $this->nonceValiditySeconds * 1000; $signatureValue = md5($expiryTime.':'.$this->key); $nonceValue = $expiryTime.':'.$signatureValue; $nonceValueBase64 = base64_encode($nonceValue); $authenticateHeader = sprintf('Digest realm="%s", qop="auth", nonce="%s"', $this->realmName, $nonceValueBase64); if ($authException instanceof NonceExpiredException) { $authenticateHeader = $authenticateHeader.', stale="true"'; } if (null !== $this->logger) { $this->logger->debug(sprintf('WWW-Authenticate header sent to user agent: "%s"', $authenticateHeader)); } $response = new Response(); $response->headers->set('WWW-Authenticate', $authenticateHeader); $response->setStatusCode(401); return $response; } /** * @return string */ public function getKey() { return $this->key; } /** * @return string */ public function getRealmName() { return $this->realmName; } } PK]:Security/Http/EntryPoint/RetryAuthenticationEntryPoint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\EntryPoint; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; /** * RetryAuthenticationEntryPoint redirects URL based on the configured scheme. * * This entry point is not intended to work with HTTP post requests. * * @author Fabien Potencier */ class RetryAuthenticationEntryPoint implements AuthenticationEntryPointInterface { private $httpPort; private $httpsPort; public function __construct($httpPort = 80, $httpsPort = 443) { $this->httpPort = $httpPort; $this->httpsPort = $httpsPort; } /** * {@inheritdoc} */ public function start(Request $request, AuthenticationException $authException = null) { $scheme = $request->isSecure() ? 'http' : 'https'; if ('http' === $scheme && 80 != $this->httpPort) { $port = ':'.$this->httpPort; } elseif ('https' === $scheme && 443 != $this->httpsPort) { $port = ':'.$this->httpsPort; } else { $port = ''; } $qs = $request->getQueryString(); if (null !== $qs) { $qs = '?'.$qs; } $url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$request->getPathInfo().$qs; return new RedirectResponse($url, 301); } } PK]<ݐpp:Security/Http/EntryPoint/BasicAuthenticationEntryPoint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\EntryPoint; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; /** * BasicAuthenticationEntryPoint starts an HTTP Basic authentication. * * @author Fabien Potencier */ class BasicAuthenticationEntryPoint implements AuthenticationEntryPointInterface { private $realmName; public function __construct($realmName) { $this->realmName = $realmName; } /** * {@inheritdoc} */ public function start(Request $request, AuthenticationException $authException = null) { $response = new Response(); $response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName)); $response->setStatusCode(401); return $response; } } PK])'_++>Security/Http/EntryPoint/AuthenticationEntryPointInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\EntryPoint; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * AuthenticationEntryPointInterface is the interface used to start the * authentication scheme. * * @author Fabien Potencier */ interface AuthenticationEntryPointInterface { /** * Starts the authentication scheme. * * @param Request $request The request that resulted in an AuthenticationException * @param AuthenticationException $authException The exception that started the authentication process * * @return Response */ public function start(Request $request, AuthenticationException $authException = null); } PK]/Security/Resources/translations/security.vi.xlfnu[ An authentication exception occurred. Có lỗi trong quá trình xác thực. Authentication credentials could not be found. Thông tin dùng để xác thực không tìm thấy. Authentication request could not be processed due to a system problem. Yêu cầu xác thực không thể thực hiện do lỗi của hệ thống. Invalid credentials. Thông tin dùng để xác thực không hợp lệ. Cookie has already been used by someone else. Cookie đã được dùng bởi người dùng khác. Not privileged to request the resource. Không được phép yêu cầu tài nguyên. Invalid CSRF token. Mã CSRF không hợp lệ. Digest nonce has expired. Mã dùng một lần đã hết hạn. No authentication provider found to support the authentication token. Không tìm thấy nhà cung cấp dịch vụ xác thực nào cho mã xác thực mà bạn sử dụng. No session available, it either timed out or cookies are not enabled. Không tìm thấy phiên làm việc. Phiên làm việc hoặc cookie có thể bị tắt. No token could be found. Không tìm thấy mã token. Username could not be found. Không tìm thấy tên người dùng username. Account has expired. Tài khoản đã hết hạn. Credentials have expired. Thông tin xác thực đã hết hạn. Account is disabled. Tài khoản bị tạm ngừng. Account is locked. Tài khoản bị khóa. PK]U/Security/Resources/translations/security.el.xlfnu[ An authentication exception occurred. Συνέβη ένα σφάλμα πιστοποίησης. Authentication credentials could not be found. Τα στοιχεία πιστοποίησης δε βρέθηκαν. Authentication request could not be processed due to a system problem. Το αίτημα πιστοποίησης δε μπορεί να επεξεργαστεί λόγω σφάλματος του συστήματος. Invalid credentials. Λανθασμένα στοιχεία σύνδεσης. Cookie has already been used by someone else. Το Cookie έχει ήδη χρησιμοποιηθεί από κάποιον άλλο. Not privileged to request the resource. Δεν είστε εξουσιοδοτημένος για πρόσβαση στο συγκεκριμένο περιεχόμενο. Invalid CSRF token. Μη έγκυρο CSRF token. Digest nonce has expired. Το digest nonce έχει λήξει. No authentication provider found to support the authentication token. Δε βρέθηκε κάποιος πάροχος πιστοποίησης που να υποστηρίζει το token πιστοποίησης. No session available, it either timed out or cookies are not enabled. Δεν υπάρχει ενεργή σύνοδος (session), είτε έχει λήξει ή τα cookies δεν είναι ενεργοποιημένα. No token could be found. Δεν ήταν δυνατόν να βρεθεί κάποιο token. Username could not be found. Το Username δε βρέθηκε. Account has expired. Ο λογαριασμός έχει λήξει. Credentials have expired. Τα στοιχεία σύνδεσης έχουν λήξει. Account is disabled. Ο λογαριασμός είναι απενεργοποιημένος. Account is locked. Ο λογαριασμός είναι κλειδωμένος. PK]5˙/Security/Resources/translations/security.ua.xlfnu[ An authentication exception occurred. Помилка автентифікації. Authentication credentials could not be found. Автентифікаційні дані не знайдено. Authentication request could not be processed due to a system problem. Запит на автентифікацію не може бути опрацьовано у зв’язку з проблемою в системі. Invalid credentials. Невірні автентифікаційні дані. Cookie has already been used by someone else. Хтось інший вже використав цей сookie. Not privileged to request the resource. Відсутні права на запит цього ресурсу. Invalid CSRF token. Невірний токен CSRF. Digest nonce has expired. Закінчився термін дії одноразового ключа дайджесту. No authentication provider found to support the authentication token. Не знайдено провайдера автентифікації, що підтримує токен автентифікаціії. No session available, it either timed out or cookies are not enabled. Сесія недоступна, її час вийшов, або cookies вимкнено. No token could be found. Токен не знайдено. Username could not be found. Ім’я користувача не знайдено. Account has expired. Термін дії облікового запису вичерпано. Credentials have expired. Термін дії автентифікаційних даних вичерпано. Account is disabled. Обліковий запис відключено. Account is locked. Обліковий запис заблоковано. PK]O /Security/Resources/translations/security.it.xlfnu[ An authentication exception occurred. Si è verificato un errore di autenticazione. Authentication credentials could not be found. Impossibile trovare le credenziali di autenticazione. Authentication request could not be processed due to a system problem. La richiesta di autenticazione non può essere processata a causa di un errore di sistema. Invalid credentials. Credenziali non valide. Cookie has already been used by someone else. Il cookie è già stato usato da qualcun altro. Not privileged to request the resource. Non hai i privilegi per richiedere questa risorsa. Invalid CSRF token. CSRF token non valido. Digest nonce has expired. Il numero di autenticazione è scaduto. No authentication provider found to support the authentication token. Non è stato trovato un valido fornitore di autenticazione per supportare il token. No session available, it either timed out or cookies are not enabled. Nessuna sessione disponibile, può essere scaduta o i cookie non sono abilitati. No token could be found. Nessun token trovato. Username could not be found. Username non trovato. Account has expired. Account scaduto. Credentials have expired. Credenziali scadute. Account is disabled. L'account è disabilitato. Account is locked. L'account è bloccato. PK]) /Security/Resources/translations/security.ro.xlfnu[ An authentication exception occurred. A apărut o eroare de autentificare. Authentication credentials could not be found. Informațiile de autentificare nu au fost găsite. Authentication request could not be processed due to a system problem. Sistemul nu a putut procesa cererea de autentificare din cauza unei erori. Invalid credentials. Date de autentificare invalide. Cookie has already been used by someone else. Cookieul este folosit deja de altcineva. Not privileged to request the resource. Permisiuni insuficiente pentru resursa cerută. Invalid CSRF token. Tokenul CSRF este invalid. Digest nonce has expired. Tokenul temporar a expirat. No authentication provider found to support the authentication token. Nu a fost găsit nici un agent de autentificare pentru tokenul specificat. No session available, it either timed out or cookies are not enabled. Sesiunea nu mai este disponibilă, a expirat sau suportul pentru cookieuri nu este activat. No token could be found. Tokenul nu a putut fi găsit. Username could not be found. Numele de utilizator nu a fost găsit. Account has expired. Contul a expirat. Credentials have expired. Datele de autentificare au expirat. Account is disabled. Contul este dezactivat. Account is locked. Contul este blocat. PK]m|JJ4Security/Resources/translations/security.sr_Cyrl.xlfnu[ An authentication exception occurred. Изузетак при аутентификацији. Authentication credentials could not be found. Аутентификациони подаци нису пронађени. Authentication request could not be processed due to a system problem. Захтев за аутентификацију не може бити обрађен због системских проблема. Invalid credentials. Невалидни подаци за аутентификацију. Cookie has already been used by someone else. Колачић је већ искоришћен од стране неког другог. Not privileged to request the resource. Немате права приступа овом ресурсу. Invalid CSRF token. Невалидан CSRF токен. Digest nonce has expired. Време криптографског кључа је истекло. No authentication provider found to support the authentication token. Аутентификациони провајдер за подршку токена није пронађен. No session available, it either timed out or cookies are not enabled. Сесија није доступна, истекла је или су колачићи искључени. No token could be found. Токен не може бити пронађен. Username could not be found. Корисничко име не може бити пронађено. Account has expired. Налог је истекао. Credentials have expired. Подаци за аутентификацију су истекли. Account is disabled. Налог је онемогућен. Account is locked. Налог је закључан. PK]YWg g 4Security/Resources/translations/security.sr_Latn.xlfnu[ An authentication exception occurred. Izuzetak pri autentifikaciji. Authentication credentials could not be found. Autentifikacioni podaci nisu pronađeni. Authentication request could not be processed due to a system problem. Zahtev za autentifikaciju ne može biti obrađen zbog sistemskih problema. Invalid credentials. Nevalidni podaci za autentifikaciju. Cookie has already been used by someone else. Kolačić je već iskorišćen od strane nekog drugog. Not privileged to request the resource. Nemate prava pristupa ovom resursu. Invalid CSRF token. Nevalidan CSRF token. Digest nonce has expired. Vreme kriptografskog ključa je isteklo. No authentication provider found to support the authentication token. Autentifikacioni provajder za podršku tokena nije pronađen. No session available, it either timed out or cookies are not enabled. Sesija nije dostupna, istekla je ili su kolačići isključeni. No token could be found. Token ne može biti pronađen. Username could not be found. Korisničko ime ne može biti pronađeno. Account has expired. Nalog je istekao. Credentials have expired. Podaci za autentifikaciju su istekli. Account is disabled. Nalog je onemogućen. Account is locked. Nalog je zaključan. PK]|H /Security/Resources/translations/security.hu.xlfnu[ An authentication exception occurred. Hitelesítési hiba lépett fel. Authentication credentials could not be found. Nem találhatók hitelesítési információk. Authentication request could not be processed due to a system problem. A hitelesítési kérést rendszerhiba miatt nem lehet feldolgozni. Invalid credentials. Érvénytelen hitelesítési információk. Cookie has already been used by someone else. Ezt a sütit valaki más már felhasználta. Not privileged to request the resource. Nem rendelkezik az erőforrás eléréséhez szükséges jogosultsággal. Invalid CSRF token. Érvénytelen CSRF token. Digest nonce has expired. A kivonat bélyege (nonce) lejárt. No authentication provider found to support the authentication token. Nem található a hitelesítési tokent támogató hitelesítési szolgáltatás. No session available, it either timed out or cookies are not enabled. Munkamenet nem áll rendelkezésre, túllépte az időkeretet vagy a sütik le vannak tiltva. No token could be found. Nem található token. Username could not be found. A felhasználónév nem található. Account has expired. A fiók lejárt. Credentials have expired. A hitelesítési információk lejártak. Account is disabled. Felfüggesztett fiók. Account is locked. Zárolt fiók. PK]ţ /Security/Resources/translations/security.ca.xlfnu[ An authentication exception occurred. Ha succeït un error d'autenticació. Authentication credentials could not be found. No s'han trobat les credencials d'autenticació. Authentication request could not be processed due to a system problem. La solicitud d'autenticació no s'ha pogut processar per un problema del sistema. Invalid credentials. Credencials no vàlides. Cookie has already been used by someone else. La cookie ja ha estat utilitzada per una altra persona. Not privileged to request the resource. No té privilegis per solicitar el recurs. Invalid CSRF token. Token CSRF no vàlid. Digest nonce has expired. El vector d'inicialització (digest nonce) ha expirat. No authentication provider found to support the authentication token. No s'ha trobat un proveïdor d'autenticació que suporti el token d'autenticació. No session available, it either timed out or cookies are not enabled. No hi ha sessió disponible, ha expirat o les cookies no estan habilitades. No token could be found. No s'ha trobat cap token. Username could not be found. No s'ha trobat el nom d'usuari. Account has expired. El compte ha expirat. Credentials have expired. Les credencials han expirat. Account is disabled. El compte està deshabilitat. Account is locked. El compte està bloquejat. PK]y /Security/Resources/translations/security.gl.xlfnu[ An authentication exception occurred. Ocorreu un erro de autenticación. Authentication credentials could not be found. Non se atoparon as credenciais de autenticación. Authentication request could not be processed due to a system problem. A solicitude de autenticación no puido ser procesada debido a un problema do sistema. Invalid credentials. Credenciais non válidas. Cookie has already been used by someone else. A cookie xa foi empregado por outro usuario. Not privileged to request the resource. Non ten privilexios para solicitar o recurso. Invalid CSRF token. Token CSRF non válido. Digest nonce has expired. O vector de inicialización (digest nonce) expirou. No authentication provider found to support the authentication token. Non se atopou un provedor de autenticación que soporte o token de autenticación. No session available, it either timed out or cookies are not enabled. Non hai ningunha sesión dispoñible, expirou ou as cookies non están habilitadas. No token could be found. Non se atopou ningún token. Username could not be found. Non se atopou o nome de usuario. Account has expired. A conta expirou. Credentials have expired. As credenciais expiraron. Account is disabled. A conta está deshabilitada. Account is locked. A conta está bloqueada. PK] /Security/Resources/translations/security.lb.xlfnu[ An authentication exception occurred. Bei der Authentifikatioun ass e Feeler opgetrueden. Authentication credentials could not be found. Et konnte keng Zouganksdate fonnt ginn. Authentication request could not be processed due to a system problem. D'Ufro fir eng Authentifikatioun konnt wéinst engem Problem vum System net beaarbecht ginn. Invalid credentials. Ongëlteg Zouganksdaten. Cookie has already been used by someone else. De Cookie gouf scho vun engem anere benotzt. Not privileged to request the resource. Keng Rechter fir d'Ressource unzefroen. Invalid CSRF token. Ongëltegen CSRF-Token. Digest nonce has expired. Den eemolege Schlëssel ass ofgelaf. No authentication provider found to support the authentication token. Et gouf keen Authentifizéierungs-Provider fonnt deen den Authentifizéierungs-Token ënnerstëtzt. No session available, it either timed out or cookies are not enabled. Keng Sëtzung disponibel. Entweder ass se ofgelaf oder Cookies sinn net aktivéiert. No token could be found. Et konnt keen Token fonnt ginn. Username could not be found. De Benotzernumm konnt net fonnt ginn. Account has expired. Den Account ass ofgelaf. Credentials have expired. D'Zouganksdate sinn ofgelaf. Account is disabled. De Konto ass deaktivéiert. Account is locked. De Konto ass gespaart. PK]o'N /Security/Resources/translations/security.de.xlfnu[ An authentication exception occurred. Es ist ein Fehler bei der Authentifikation aufgetreten. Authentication credentials could not be found. Es konnten keine Zugangsdaten gefunden werden. Authentication request could not be processed due to a system problem. Die Authentifikation konnte wegen eines Systemproblems nicht bearbeitet werden. Invalid credentials. Fehlerhafte Zugangsdaten. Cookie has already been used by someone else. Cookie wurde bereits von jemand anderem verwendet. Not privileged to request the resource. Keine Rechte, um die Ressource anzufragen. Invalid CSRF token. Ungültiges CSRF-Token. Digest nonce has expired. Digest nonce ist abgelaufen. No authentication provider found to support the authentication token. Es wurde kein Authentifizierungs-Provider gefunden, der das Authentifizierungs-Token unterstützt. No session available, it either timed out or cookies are not enabled. Keine Session verfügbar, entweder ist diese abgelaufen oder Cookies sind nicht aktiviert. No token could be found. Es wurde kein Token gefunden. Username could not be found. Der Benutzername wurde nicht gefunden. Account has expired. Der Account ist abgelaufen. Credentials have expired. Die Zugangsdaten sind abgelaufen. Account is disabled. Der Account ist deaktiviert. Account is locked. Der Account ist gesperrt. PK].X: : /Security/Resources/translations/security.en.xlfnu[ An authentication exception occurred. An authentication exception occurred. Authentication credentials could not be found. Authentication credentials could not be found. Authentication request could not be processed due to a system problem. Authentication request could not be processed due to a system problem. Invalid credentials. Invalid credentials. Cookie has already been used by someone else. Cookie has already been used by someone else. Not privileged to request the resource. Not privileged to request the resource. Invalid CSRF token. Invalid CSRF token. Digest nonce has expired. Digest nonce has expired. No authentication provider found to support the authentication token. No authentication provider found to support the authentication token. No session available, it either timed out or cookies are not enabled. No session available, it either timed out or cookies are not enabled. No token could be found. No token could be found. Username could not be found. Username could not be found. Account has expired. Account has expired. Credentials have expired. Credentials have expired. Account is disabled. Account is disabled. Account is locked. Account is locked. PK](SS/Security/Resources/translations/security.bg.xlfnu[ An authentication exception occurred. Грешка при автентикация. Authentication credentials could not be found. Удостоверението за автентикация не е открито. Authentication request could not be processed due to a system problem. Заявката за автентикация не може да бъде обработената поради системна грешка. Invalid credentials. Невалидно удостоверение за автентикация. Cookie has already been used by someone else. Това cookie вече се ползва от някой друг. Not privileged to request the resource. Нямате права за достъп до този ресурс. Invalid CSRF token. Невалиден CSRF токен. Digest nonce has expired. Digest nonce е изтекъл. No authentication provider found to support the authentication token. Не е открит провайдър, който да поддържа този токен за автентикация. No session available, it either timed out or cookies are not enabled. Сесията не е достъпна, или времето за достъп е изтекло, или кукитата не са разрешени. No token could be found. Токена не е открит. Username could not be found. Потребителското име не е открито. Account has expired. Акаунта е изтекъл. Credentials have expired. Удостоверението за автентикация е изтекло. Account is disabled. Акаунта е деактивиран. Account is locked. Акаунта е заключен. PK]f488/Security/Resources/translations/security.ja.xlfnu[ An authentication exception occurred. 認証エラーが発生しました。 Authentication credentials could not be found. 認証資格がありません。 Authentication request could not be processed due to a system problem. システムの問題により認証要求を処理できませんでした。 Invalid credentials. 資格が無効です。 Cookie has already been used by someone else. Cookie が別のユーザーで使用されています。 Not privileged to request the resource. リソースをリクエストする権限がありません。 Invalid CSRF token. CSRF トークンが無効です。 Digest nonce has expired. Digest の nonce 値が期限切れです。 No authentication provider found to support the authentication token. 認証トークンをサポートする認証プロバイダーが見つかりません。 No session available, it either timed out or cookies are not enabled. 利用可能なセッションがありません。タイムアウトしたか、Cookie が無効になっています。 No token could be found. トークンが見つかりません。 Username could not be found. ユーザー名が見つかりません。 Account has expired. アカウントが有効期限切れです。 Credentials have expired. 資格が有効期限切れです。 Account is disabled. アカウントが無効です。 Account is locked. アカウントはロックされています。 PK] /Security/Resources/translations/security.no.xlfnu[ An authentication exception occurred. En autentiserings feil har skjedd. Authentication credentials could not be found. Påloggingsinformasjonen kunne ikke bli funnet. Authentication request could not be processed due to a system problem. Autentiserings forespørselen kunne ikke bli prosessert grunnet en system feil. Invalid credentials. Ugyldig påloggingsinformasjonen. Cookie has already been used by someone else. Cookie har allerede blitt brukt av noen andre. Not privileged to request the resource. Ingen tilgang til å be om gitt kilde. Invalid CSRF token. Ugyldig CSRF token. Digest nonce has expired. Digest nonce er utløpt. No authentication provider found to support the authentication token. Ingen autentiserings tilbyder funnet som støtter gitt autentiserings token. No session available, it either timed out or cookies are not enabled. Ingen sesjon tilgjengelig, sesjonen er enten utløpt eller cookies ikke skrudd på. No token could be found. Ingen token kunne bli funnet. Username could not be found. Brukernavn kunne ikke bli funnet. Account has expired. Brukerkonto har utgått. Credentials have expired. Påloggingsinformasjon har utløpt. Account is disabled. Brukerkonto er deaktivert. Account is locked. Brukerkonto er sperret. PK]M-@/Security/Resources/translations/security.fa.xlfnu[ An authentication exception occurred. خطایی هنگام تعیین اعتبار اتفاق افتاد. Authentication credentials could not be found. شرایط تعیین اعتبار پیدا نشد. Authentication request could not be processed due to a system problem. درخواست تعیین اعتبار به دلیل مشکل سیستم قابل بررسی نیست. Invalid credentials. شرایط نامعتبر. Cookie has already been used by someone else. کوکی قبلا برای شخص دیگری استفاده شده است. Not privileged to request the resource. دسترسی لازم برای درخواست این منبع را ندارید. Invalid CSRF token. توکن CSRF معتبر نیست. Digest nonce has expired. Digest nonce منقضی شده است. No authentication provider found to support the authentication token. هیچ ارایه کننده تعیین اعتباری برای ساپورت توکن تعیین اعتبار پیدا نشد. No session available, it either timed out or cookies are not enabled. جلسه‌ای در دسترس نیست. این میتواند یا به دلیل پایان یافتن زمان باشد یا اینکه کوکی ها فعال نیستند. No token could be found. هیچ توکنی پیدا نشد. Username could not be found. نام ‌کاربری پیدا نشد. Account has expired. حساب کاربری منقضی شده است. Credentials have expired. پارامترهای تعیین اعتبار منقضی شده‌اند. Account is disabled. حساب کاربری غیرفعال است. Account is locked. حساب کاربری قفل شده است. PK]J J /Security/Resources/translations/security.da.xlfnu[ An authentication exception occurred. En fejl indtraf ved godkendelse. Authentication credentials could not be found. Loginoplysninger kan findes. Authentication request could not be processed due to a system problem. Godkendelsesanmodning kan ikke behandles på grund af et systemfejl. Invalid credentials. Ugyldige loginoplysninger. Cookie has already been used by someone else. Cookie er allerede brugt af en anden. Not privileged to request the resource. Ingen tilladselese at anvende kilden. Invalid CSRF token. Ugyldigt CSRF token. Digest nonce has expired. Digest nonce er udløbet. No authentication provider found to support the authentication token. Ingen godkendelsesudbyder er fundet til understøttelsen af godkendelsestoken. No session available, it either timed out or cookies are not enabled. Ingen session tilgængelig, sessionen er enten udløbet eller cookies er ikke aktiveret. No token could be found. Ingen token kan findes. Username could not be found. Brugernavn kan ikke findes. Account has expired. Brugerkonto er udløbet. Credentials have expired. Loginoplysninger er udløbet. Account is disabled. Brugerkonto er deaktiveret. Account is locked. Brugerkonto er låst. PK]]W W /Security/Resources/translations/security.hr.xlfnu[ An authentication exception occurred. Dogodila se autentifikacijske iznimka. Authentication credentials could not be found. Autentifikacijski podaci nisu pronađeni. Authentication request could not be processed due to a system problem. Autentifikacijski zahtjev nije moguće provesti uslijed sistemskog problema. Invalid credentials. Neispravni akreditacijski podaci. Cookie has already been used by someone else. Cookie je već netko drugi iskoristio. Not privileged to request the resource. Nemate privilegije zahtijevati resurs. Invalid CSRF token. Neispravan CSRF token. Digest nonce has expired. Digest nonce je isteko. No authentication provider found to support the authentication token. Nije pronađen autentifikacijski provider koji bi podržao autentifikacijski token. No session available, it either timed out or cookies are not enabled. Sesija nije dostupna, ili je istekla ili cookies nisu omogućeni. No token could be found. Token nije pronađen. Username could not be found. Korisničko ime nije pronađeno. Account has expired. Račun je isteko. Credentials have expired. Akreditacijski podaci su istekli. Account is disabled. Račun je onemogućen. Account is locked. Račun je zaključan. PK]&MЎ /Security/Resources/translations/security.es.xlfnu[ An authentication exception occurred. Ocurrió un error de autenticación. Authentication credentials could not be found. No se encontraron las credenciales de autenticación. Authentication request could not be processed due to a system problem. La solicitud de autenticación no se pudo procesar debido a un problema del sistema. Invalid credentials. Credenciales no válidas. Cookie has already been used by someone else. La cookie ya ha sido usada por otra persona. Not privileged to request the resource. No tiene privilegios para solicitar el recurso. Invalid CSRF token. Token CSRF no válido. Digest nonce has expired. El vector de inicialización (digest nonce) ha expirado. No authentication provider found to support the authentication token. No se encontró un proveedor de autenticación que soporte el token de autenticación. No session available, it either timed out or cookies are not enabled. No hay ninguna sesión disponible, ha expirado o las cookies no están habilitados. No token could be found. No se encontró ningún token. Username could not be found. No se encontró el nombre de usuario. Account has expired. La cuenta ha expirado. Credentials have expired. Las credenciales han expirado. Account is disabled. La cuenta está deshabilitada. Account is locked. La cuenta está bloqueada. PK]Y 2Security/Resources/translations/security.pt_BR.xlfnu[ An authentication exception occurred. Uma exceção ocorreu durante a autenticação. Authentication credentials could not be found. As credenciais de autenticação não foram encontradas. Authentication request could not be processed due to a system problem. A autenticação não pôde ser concluída devido a um problema no sistema. Invalid credentials. Credenciais inválidas. Cookie has already been used by someone else. Este cookie já está em uso. Not privileged to request the resource. Não possui privilégios o bastante para requisitar este recurso. Invalid CSRF token. Token CSRF inválido. Digest nonce has expired. Digest nonce expirado. No authentication provider found to support the authentication token. Nenhum provedor de autenticação encontrado para suportar o token de autenticação. No session available, it either timed out or cookies are not enabled. Nenhuma sessão disponível, ela expirou ou os cookies estão desativados. No token could be found. Nenhum token foi encontrado. Username could not be found. Nome de usuário não encontrado. Account has expired. A conta está expirada. Credentials have expired. As credenciais estão expiradas. Account is disabled. Conta desativada. Account is locked. A conta está travada. PK] ( /Security/Resources/translations/security.cs.xlfnu[ An authentication exception occurred. Při ověřování došlo k chybě. Authentication credentials could not be found. Ověřovací údaje nebyly nalezeny. Authentication request could not be processed due to a system problem. Požadavek na ověření nemohl být zpracován kvůli systémové chybě. Invalid credentials. Neplatné přihlašovací údaje. Cookie has already been used by someone else. Cookie již bylo použité někým jiným. Not privileged to request the resource. Nemáte oprávnění přistupovat k prostředku. Invalid CSRF token. Neplatný CSRF token. Digest nonce has expired. Platnost inicializačního vektoru (digest nonce) vypršela. No authentication provider found to support the authentication token. Poskytovatel pro ověřovací token nebyl nalezen. No session available, it either timed out or cookies are not enabled. Session není k dispozici, vypršela její platnost, nebo jsou zakázané cookies. No token could be found. Token nebyl nalezen. Username could not be found. Přihlašovací jméno nebylo nalezeno. Account has expired. Platnost účtu vypršela. Credentials have expired. Platnost přihlašovacích údajů vypršela. Account is disabled. Účet je zakázaný. Account is locked. Účet je zablokovaný. PK]Dt 2Security/Resources/translations/security.zh_CN.xlfnu[ An authentication exception occurred. 身份验证发生异常。 Authentication credentials could not be found. 没有找到身份验证的凭证。 Authentication request could not be processed due to a system problem. 由于系统故障,身份验证的请求无法被处理。 Invalid credentials. 无效的凭证。 Cookie has already been used by someone else. Cookie 已经被其他人使用。 Not privileged to request the resource. 没有权限请求此资源。 Invalid CSRF token. 无效的 CSRF token 。 Digest nonce has expired. 摘要随机串(digest nonce)已过期。 No authentication provider found to support the authentication token. 没有找到支持此 token 的身份验证服务提供方。 No session available, it either timed out or cookies are not enabled. Session 不可用。会话超时或没有启用 cookies 。 No token could be found. 找不到 token 。 Username could not be found. 找不到用户名。 Account has expired. 帐号已过期。 Credentials have expired. 凭证已过期。 Account is disabled. 帐号已被禁用。 Account is locked. 帐号已被锁定。 PK]w=/Security/Resources/translations/security.ru.xlfnu[ An authentication exception occurred. Ошибка аутентификации. Authentication credentials could not be found. Аутентификационные данные не найдены. Authentication request could not be processed due to a system problem. Запрос аутентификации не может быть обработан в связи с проблемой в системе. Invalid credentials. Недействительные аутентификационные данные. Cookie has already been used by someone else. Cookie уже был использован кем-то другим. Not privileged to request the resource. Отсутствуют права на запрос этого ресурса. Invalid CSRF token. Недействительный токен CSRF. Digest nonce has expired. Время действия одноразового ключа дайджеста истекло. No authentication provider found to support the authentication token. Не найден провайдер аутентификации, поддерживающий токен аутентификации. No session available, it either timed out or cookies are not enabled. Сессия не найдена, ее время истекло, либо cookies не включены. No token could be found. Токен не найден. Username could not be found. Имя пользователя не найдено. Account has expired. Время действия учетной записи истекло. Credentials have expired. Время действия аутентификационных данных истекло. Account is disabled. Учетная запись отключена. Account is locked. Учетная запись заблокирована. PK]Tkf/Security/Resources/translations/security.ar.xlfnu[ An authentication exception occurred. حدث خطأ اثناء الدخول. Authentication credentials could not be found. لم استطع العثور على معلومات الدخول. Authentication request could not be processed due to a system problem. لم يكتمل طلب الدخول نتيجه عطل فى النظام. Invalid credentials. معلومات الدخول خاطئة. Cookie has already been used by someone else. ملفات تعريف الارتباط(cookies) تم استخدامها من قبل شخص اخر. Not privileged to request the resource. ليست لديك الصلاحيات الكافية لهذا الطلب. Invalid CSRF token. رمز الموقع غير صحيح. Digest nonce has expired. انتهت صلاحية(digest nonce). No authentication provider found to support the authentication token. لا يوجد معرف للدخول يدعم الرمز المستخدم للدخول. No session available, it either timed out or cookies are not enabled. لا يوجد صلة بينك و بين الموقع اما انها انتهت او ان متصفحك لا يدعم خاصية ملفات تعريف الارتباط (cookies). No token could be found. لم استطع العثور على الرمز. Username could not be found. لم استطع العثور على اسم الدخول. Account has expired. انتهت صلاحية الحساب. Credentials have expired. انتهت صلاحية معلومات الدخول. Account is disabled. الحساب موقوف. Account is locked. الحساب مغلق. PK]RwD D /Security/Resources/translations/security.id.xlfnu[ An authentication exception occurred. Terjadi sebuah pengecualian otentikasi. Authentication credentials could not be found. Kredensial otentikasi tidak bisa ditemukan. Authentication request could not be processed due to a system problem. Permintaan otentikasi tidak bisa diproses karena masalah sistem. Invalid credentials. Kredensial salah. Cookie has already been used by someone else. Cookie sudah digunakan oleh orang lain. Not privileged to request the resource. Tidak berhak untuk meminta sumber daya. Invalid CSRF token. Token CSRF salah. Digest nonce has expired. Digest nonce telah berakhir. No authentication provider found to support the authentication token. Tidak ditemukan penyedia otentikasi untuk mendukung token otentikasi. No session available, it either timed out or cookies are not enabled. Tidak ada sesi yang tersedia, mungkin waktu sudah habis atau cookie tidak diaktifkan No token could be found. Tidak ada token yang bisa ditemukan. Username could not be found. Username tidak bisa ditemukan. Account has expired. Akun telah berakhir. Credentials have expired. Kredensial telah berakhir. Account is disabled. Akun dinonaktifkan. Account is locked. Akun terkunci. PK]'{ { /Security/Resources/translations/security.tr.xlfnu[ An authentication exception occurred. Bir yetkilendirme istisnası oluştu. Authentication credentials could not be found. Yetkilendirme girdileri bulunamadı. Authentication request could not be processed due to a system problem. Bir sistem hatası nedeniyle yetkilendirme isteği işleme alınamıyor. Invalid credentials. Geçersiz girdiler. Cookie has already been used by someone else. Çerez bir başkası tarafından zaten kullanılmıştı. Not privileged to request the resource. Kaynak talebi için imtiyaz bulunamadı. Invalid CSRF token. Geçersiz CSRF fişi. Digest nonce has expired. Derleme zaman aşımı gerçekleşti. No authentication provider found to support the authentication token. Yetkilendirme fişini destekleyecek yetkilendirme sağlayıcısı bulunamadı. No session available, it either timed out or cookies are not enabled. Oturum bulunamadı, zaman aşımına uğradı veya çerezler etkin değil. No token could be found. Bilet bulunamadı. Username could not be found. Kullanıcı adı bulunamadı. Account has expired. Hesap zaman aşımına uğradı. Credentials have expired. Girdiler zaman aşımına uğradı. Account is disabled. Hesap devre dışı bırakılmış. Account is locked. Hesap kilitlenmiş. PK]de /Security/Resources/translations/security.fr.xlfnu[ An authentication exception occurred. Une exception d'authentification s'est produite. Authentication credentials could not be found. Les droits d'authentification n'ont pas pu être trouvés. Authentication request could not be processed due to a system problem. La requête d'authentification n'a pas pu être executée à cause d'un problème système. Invalid credentials. Droits invalides. Cookie has already been used by someone else. Le cookie a déjà été utilisé par quelqu'un d'autre. Not privileged to request the resource. Pas de privilèges pour accéder à la ressource. Invalid CSRF token. Jeton CSRF invalide. Digest nonce has expired. Le digest nonce a expiré. No authentication provider found to support the authentication token. Aucun fournisseur d'authentification n'a été trouvé pour supporter le jeton d'authentification. No session available, it either timed out or cookies are not enabled. Pas de session disponible, celle-ci a expiré ou les cookies ne sont pas activés. No token could be found. Aucun jeton n'a pu être trouvé. Username could not be found. Le nom d'utilisateur ne peut pas être trouvé. Account has expired. Le compte a expiré. Credentials have expired. Les droits ont expirés. Account is disabled. Le compte est désactivé. Account is locked. Le compte est bloqué. PK]u^ ^ /Security/Resources/translations/security.sv.xlfnu[ An authentication exception occurred. Ett autentiseringsfel har inträffat. Authentication credentials could not be found. Uppgifterna för autentisering kunde inte hittas. Authentication request could not be processed due to a system problem. Autentiseringen kunde inte genomföras på grund av systemfel. Invalid credentials. Felaktiga uppgifter. Cookie has already been used by someone else. Cookien har redan använts av någon annan. Not privileged to request the resource. Saknar rättigheter för resursen. Invalid CSRF token. Ogiltig CSRF-token. Digest nonce has expired. Förfallen digest nonce. No authentication provider found to support the authentication token. Ingen leverantör för autentisering hittades för angiven autentiseringstoken. No session available, it either timed out or cookies are not enabled. Ingen session finns tillgänglig, antingen har den förfallit eller är cookies inte aktiverat. No token could be found. Ingen token kunde hittas. Username could not be found. Användarnamnet kunde inte hittas. Account has expired. Kontot har förfallit. Credentials have expired. Uppgifterna har förfallit. Account is disabled. Kontot är inaktiverat. Account is locked. Kontot är låst. PK]d /Security/Resources/translations/security.pl.xlfnu[ An authentication exception occurred. Wystąpił błąd uwierzytelniania. Authentication credentials could not be found. Dane uwierzytelniania nie zostały znalezione. Authentication request could not be processed due to a system problem. Żądanie uwierzytelniania nie mogło zostać pomyślnie zakończone z powodu problemu z systemem. Invalid credentials. Nieprawidłowe dane. Cookie has already been used by someone else. To ciasteczko jest używane przez kogoś innego. Not privileged to request the resource. Brak uprawnień dla żądania wskazanego zasobu. Invalid CSRF token. Nieprawidłowy token CSRF. Digest nonce has expired. Kod dostępu wygasł. No authentication provider found to support the authentication token. Nie znaleziono mechanizmu uwierzytelniania zdolnego do obsługi przesłanego tokenu. No session available, it either timed out or cookies are not enabled. Brak danych sesji, sesja wygasła lub ciasteczka nie są włączone. No token could be found. Nie znaleziono tokenu. Username could not be found. Użytkownik o podanej nazwie nie istnieje. Account has expired. Konto wygasło. Credentials have expired. Dane uwierzytelniania wygasły. Account is disabled. Konto jest wyłączone. Account is locked. Konto jest zablokowane. PK]UɎd d /Security/Resources/translations/security.sl.xlfnu[ An authentication exception occurred. Prišlo je do izjeme pri preverjanju avtentikacije. Authentication credentials could not be found. Poverilnic za avtentikacijo ni bilo mogoče najti. Authentication request could not be processed due to a system problem. Zahteve za avtentikacijo ni bilo mogoče izvesti zaradi sistemske težave. Invalid credentials. Neveljavne pravice. Cookie has already been used by someone else. Piškotek je uporabil že nekdo drug. Not privileged to request the resource. Nimate privilegijev za zahtevani vir. Invalid CSRF token. Neveljaven CSRF žeton. Digest nonce has expired. Začasni žeton je potekel. No authentication provider found to support the authentication token. Ponudnika avtentikacije za podporo prijavnega žetona ni bilo mogoče najti. No session available, it either timed out or cookies are not enabled. Seja ni na voljo, ali je potekla ali pa piškotki niso omogočeni. No token could be found. Žetona ni bilo mogoče najti. Username could not be found. Uporabniškega imena ni bilo mogoče najti. Account has expired. Račun je potekel. Credentials have expired. Poverilnice so potekle. Account is disabled. Račun je onemogočen. Account is locked. Račun je zaklenjen. PK]#@y y 2Security/Resources/translations/security.pt_PT.xlfnu[ An authentication exception occurred. Ocorreu um excepção durante a autenticação. Authentication credentials could not be found. As credenciais de autenticação não foram encontradas. Authentication request could not be processed due to a system problem. O pedido de autenticação não foi concluído devido a um problema no sistema. Invalid credentials. Credenciais inválidas. Cookie has already been used by someone else. Este cookie já esta em uso. Not privileged to request the resource. Não possui privilégios para aceder a este recurso. Invalid CSRF token. Token CSRF inválido. Digest nonce has expired. Digest nonce expirado. No authentication provider found to support the authentication token. Nenhum fornecedor de autenticação encontrado para suportar o token de autenticação. No session available, it either timed out or cookies are not enabled. Não existe sessão disponível, esta expirou ou os cookies estão desativados. No token could be found. O token não foi encontrado. Username could not be found. Nome de utilizador não encontrado. Account has expired. A conta expirou. Credentials have expired. As credenciais expiraram. Account is disabled. Conta desativada. Account is locked. A conta esta trancada. PK]pU /Security/Resources/translations/security.nl.xlfnu[ An authentication exception occurred. Er heeft zich een authenticatieprobleem voorgedaan. Authentication credentials could not be found. Authenticatiegegevens konden niet worden gevonden. Authentication request could not be processed due to a system problem. Authenticatieaanvraag kon niet worden verwerkt door een technisch probleem. Invalid credentials. Ongeldige inloggegevens. Cookie has already been used by someone else. Cookie is al door een ander persoon gebruikt. Not privileged to request the resource. Onvoldoende rechten om de aanvraag te verwerken. Invalid CSRF token. CSRF-code is ongeldig. Digest nonce has expired. Serverauthenticatiesleutel (digest nonce) is verlopen. No authentication provider found to support the authentication token. Geen authenticatieprovider gevonden die de authenticatietoken ondersteunt. No session available, it either timed out or cookies are not enabled. Geen sessie beschikbaar, mogelijk is deze verlopen of cookies zijn uitgeschakeld. No token could be found. Er kon geen authenticatietoken worden gevonden. Username could not be found. Gebruikersnaam kon niet worden gevonden. Account has expired. Account is verlopen. Credentials have expired. Authenticatiegegevens zijn verlopen. Account is disabled. Account is gedeactiveerd. Account is locked. Account is geblokkeerd. PK]ق /Security/Resources/translations/security.sk.xlfnu[ An authentication exception occurred. Pri overovaní došlo k chybe. Authentication credentials could not be found. Overovacie údaje neboli nájdené. Authentication request could not be processed due to a system problem. Požiadavok na overenie nemohol byť spracovaný kvôli systémovej chybe. Invalid credentials. Neplatné prihlasovacie údaje. Cookie has already been used by someone else. Cookie už bolo použité niekým iným. Not privileged to request the resource. Nemáte oprávnenie pristupovať k prostriedku. Invalid CSRF token. Neplatný CSRF token. Digest nonce has expired. Platnosť inicializačného vektoru (digest nonce) skončila. No authentication provider found to support the authentication token. Poskytovateľ pre overovací token nebol nájdený. No session available, it either timed out or cookies are not enabled. Session nie je k dispozíci, vypršala jej platnosť, alebo sú zakázané cookies. No token could be found. Token nebol nájdený. Username could not be found. Prihlasovacie meno nebolo nájdené. Account has expired. Platnosť účtu skončila. Credentials have expired. Platnosť prihlasovacích údajov skončila. Account is disabled. Účet je zakázaný. Account is locked. Účet je zablokovaný. PK]fZ^ ^ 'Security/Acl/Resources/schema/mysql.sqlnu[CREATE TABLE acl_classes (id INT UNSIGNED AUTO_INCREMENT NOT NULL, class_type VARCHAR(200) NOT NULL, UNIQUE INDEX UNIQ_69DD750638A36066 (class_type), PRIMARY KEY(id)) ENGINE = InnoDB CREATE TABLE acl_security_identities (id INT UNSIGNED AUTO_INCREMENT NOT NULL, identifier VARCHAR(200) NOT NULL, username TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 (identifier, username), PRIMARY KEY(id)) ENGINE = InnoDB CREATE TABLE acl_object_identities (id INT UNSIGNED AUTO_INCREMENT NOT NULL, parent_object_identity_id INT UNSIGNED DEFAULT NULL, class_id INT UNSIGNED NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 (object_identifier, class_id), INDEX IDX_9407E54977FA751A (parent_object_identity_id), PRIMARY KEY(id)) ENGINE = InnoDB CREATE TABLE acl_object_identity_ancestors (object_identity_id INT UNSIGNED NOT NULL, ancestor_id INT UNSIGNED NOT NULL, INDEX IDX_825DE2993D9AB4A6 (object_identity_id), INDEX IDX_825DE299C671CEA1 (ancestor_id), PRIMARY KEY(object_identity_id, ancestor_id)) ENGINE = InnoDB CREATE TABLE acl_entries (id INT UNSIGNED AUTO_INCREMENT NOT NULL, class_id INT UNSIGNED NOT NULL, object_identity_id INT UNSIGNED DEFAULT NULL, security_identity_id INT UNSIGNED NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT UNSIGNED NOT NULL, mask INT NOT NULL, granting TINYINT(1) NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success TINYINT(1) NOT NULL, audit_failure TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 (class_id, object_identity_id, field_name, ace_order), INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 (class_id, object_identity_id, security_identity_id), INDEX IDX_46C8B806EA000B10 (class_id), INDEX IDX_46C8B8063D9AB4A6 (object_identity_id), INDEX IDX_46C8B806DF9183C9 (security_identity_id), PRIMARY KEY(id)) ENGINE = InnoDB ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK]Jx.  'Security/Acl/Resources/schema/mssql.sqlnu[CREATE TABLE acl_classes (id INT UNSIGNED IDENTITY NOT NULL, class_type NVARCHAR(200) NOT NULL, PRIMARY KEY (id)) CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) WHERE class_type IS NOT NULL CREATE TABLE acl_security_identities (id INT UNSIGNED IDENTITY NOT NULL, identifier NVARCHAR(200) NOT NULL, username BIT NOT NULL, PRIMARY KEY (id)) CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) WHERE identifier IS NOT NULL AND username IS NOT NULL CREATE TABLE acl_object_identities (id INT UNSIGNED IDENTITY NOT NULL, parent_object_identity_id INT UNSIGNED DEFAULT NULL, class_id INT UNSIGNED NOT NULL, object_identifier NVARCHAR(100) NOT NULL, entries_inheriting BIT NOT NULL, PRIMARY KEY (id)) CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) WHERE object_identifier IS NOT NULL AND class_id IS NOT NULL CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id) CREATE TABLE acl_object_identity_ancestors (object_identity_id INT UNSIGNED NOT NULL, ancestor_id INT UNSIGNED NOT NULL, PRIMARY KEY (object_identity_id, ancestor_id)) CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id) CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id) CREATE TABLE acl_entries (id INT UNSIGNED IDENTITY NOT NULL, class_id INT UNSIGNED NOT NULL, object_identity_id INT UNSIGNED DEFAULT NULL, security_identity_id INT UNSIGNED NOT NULL, field_name NVARCHAR(50) DEFAULT NULL, ace_order SMALLINT UNSIGNED NOT NULL, mask INT NOT NULL, granting BIT NOT NULL, granting_strategy NVARCHAR(30) NOT NULL, audit_success BIT NOT NULL, audit_failure BIT NOT NULL, PRIMARY KEY (id)) CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) WHERE class_id IS NOT NULL AND object_identity_id IS NOT NULL AND field_name IS NOT NULL AND ace_order IS NOT NULL CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id) CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id) CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id) CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id) ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK]C ;;(Security/Acl/Resources/schema/oracle.sqlnu[CREATE TABLE acl_classes (id NUMBER(10) NOT NULL, class_type VARCHAR2(200) NOT NULL, PRIMARY KEY(id)) DECLARE constraints_Count NUMBER; BEGIN SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_CLASSES' AND CONSTRAINT_TYPE = 'P'; IF constraints_Count = 0 OR constraints_Count = '' THEN EXECUTE IMMEDIATE 'ALTER TABLE ACL_CLASSES ADD CONSTRAINT ACL_CLASSES_AI_PK PRIMARY KEY (id)'; END IF; END; CREATE SEQUENCE ACL_CLASSES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1 CREATE TRIGGER ACL_CLASSES_AI_PK BEFORE INSERT ON ACL_CLASSES FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN SELECT ACL_CLASSES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; IF (:NEW.id IS NULL OR :NEW.id = 0) THEN SELECT ACL_CLASSES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; ELSE SELECT NVL(Last_Number, 0) INTO last_Sequence FROM User_Sequences WHERE Sequence_Name = 'ACL_CLASSES_SEQ'; SELECT :NEW.id INTO last_InsertID FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP SELECT ACL_CLASSES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL; END LOOP; END IF; END; CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) CREATE TABLE acl_security_identities (id NUMBER(10) NOT NULL, identifier VARCHAR2(200) NOT NULL, username NUMBER(1) NOT NULL, PRIMARY KEY(id)) DECLARE constraints_Count NUMBER; BEGIN SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_SECURITY_IDENTITIES' AND CONSTRAINT_TYPE = 'P'; IF constraints_Count = 0 OR constraints_Count = '' THEN EXECUTE IMMEDIATE 'ALTER TABLE ACL_SECURITY_IDENTITIES ADD CONSTRAINT ACL_SECURITY_IDENTITIES_AI_PK PRIMARY KEY (id)'; END IF; END; CREATE SEQUENCE ACL_SECURITY_IDENTITIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1 CREATE TRIGGER ACL_SECURITY_IDENTITIES_AI_PK BEFORE INSERT ON ACL_SECURITY_IDENTITIES FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; IF (:NEW.id IS NULL OR :NEW.id = 0) THEN SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; ELSE SELECT NVL(Last_Number, 0) INTO last_Sequence FROM User_Sequences WHERE Sequence_Name = 'ACL_SECURITY_IDENTITIES_SEQ'; SELECT :NEW.id INTO last_InsertID FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL; END LOOP; END IF; END; CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) CREATE TABLE acl_object_identities (id NUMBER(10) NOT NULL, parent_object_identity_id NUMBER(10) DEFAULT NULL, class_id NUMBER(10) NOT NULL, object_identifier VARCHAR2(100) NOT NULL, entries_inheriting NUMBER(1) NOT NULL, PRIMARY KEY(id)) DECLARE constraints_Count NUMBER; BEGIN SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_OBJECT_IDENTITIES' AND CONSTRAINT_TYPE = 'P'; IF constraints_Count = 0 OR constraints_Count = '' THEN EXECUTE IMMEDIATE 'ALTER TABLE ACL_OBJECT_IDENTITIES ADD CONSTRAINT ACL_OBJECT_IDENTITIES_AI_PK PRIMARY KEY (id)'; END IF; END; CREATE SEQUENCE ACL_OBJECT_IDENTITIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1 CREATE TRIGGER ACL_OBJECT_IDENTITIES_AI_PK BEFORE INSERT ON ACL_OBJECT_IDENTITIES FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; IF (:NEW.id IS NULL OR :NEW.id = 0) THEN SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; ELSE SELECT NVL(Last_Number, 0) INTO last_Sequence FROM User_Sequences WHERE Sequence_Name = 'ACL_OBJECT_IDENTITIES_SEQ'; SELECT :NEW.id INTO last_InsertID FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL; END LOOP; END IF; END; CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id) CREATE TABLE acl_object_identity_ancestors (object_identity_id NUMBER(10) NOT NULL, ancestor_id NUMBER(10) NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id)) CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id) CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id) CREATE TABLE acl_entries (id NUMBER(10) NOT NULL, class_id NUMBER(10) NOT NULL, object_identity_id NUMBER(10) DEFAULT NULL, security_identity_id NUMBER(10) NOT NULL, field_name VARCHAR2(50) DEFAULT NULL, ace_order NUMBER(5) NOT NULL, mask NUMBER(10) NOT NULL, granting NUMBER(1) NOT NULL, granting_strategy VARCHAR2(30) NOT NULL, audit_success NUMBER(1) NOT NULL, audit_failure NUMBER(1) NOT NULL, PRIMARY KEY(id)) DECLARE constraints_Count NUMBER; BEGIN SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_ENTRIES' AND CONSTRAINT_TYPE = 'P'; IF constraints_Count = 0 OR constraints_Count = '' THEN EXECUTE IMMEDIATE 'ALTER TABLE ACL_ENTRIES ADD CONSTRAINT ACL_ENTRIES_AI_PK PRIMARY KEY (id)'; END IF; END; CREATE SEQUENCE ACL_ENTRIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1 CREATE TRIGGER ACL_ENTRIES_AI_PK BEFORE INSERT ON ACL_ENTRIES FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; IF (:NEW.id IS NULL OR :NEW.id = 0) THEN SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; ELSE SELECT NVL(Last_Number, 0) INTO last_Sequence FROM User_Sequences WHERE Sequence_Name = 'ACL_ENTRIES_SEQ'; SELECT :NEW.id INTO last_InsertID FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL; END LOOP; END IF; END; CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id) CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id) CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id) CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id) ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON DELETE CASCADEPK]c )Security/Acl/Resources/schema/drizzle.sqlnu[CREATE TABLE acl_classes (id INT AUTO_INCREMENT NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_69DD750638A36066 (class_type)) CREATE TABLE acl_security_identities (id INT AUTO_INCREMENT NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 (identifier, username)) CREATE TABLE acl_object_identities (id INT AUTO_INCREMENT NOT NULL, parent_object_identity_id INT DEFAULT NULL, class_id INT NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 (object_identifier, class_id), INDEX IDX_9407E54977FA751A (parent_object_identity_id)) CREATE TABLE acl_object_identity_ancestors (object_identity_id INT NOT NULL, ancestor_id INT NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id), INDEX IDX_825DE2993D9AB4A6 (object_identity_id), INDEX IDX_825DE299C671CEA1 (ancestor_id)) CREATE TABLE acl_entries (id INT AUTO_INCREMENT NOT NULL, class_id INT NOT NULL, object_identity_id INT DEFAULT NULL, security_identity_id INT NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order INT NOT NULL, mask INT NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 (class_id, object_identity_id, field_name, ace_order), INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 (class_id, object_identity_id, security_identity_id), INDEX IDX_46C8B806EA000B10 (class_id), INDEX IDX_46C8B8063D9AB4A6 (object_identity_id), INDEX IDX_46C8B806DF9183C9 (security_identity_id)) ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK]Tsk k ,Security/Acl/Resources/schema/postgresql.sqlnu[CREATE TABLE acl_classes (id SERIAL NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) CREATE TABLE acl_security_identities (id SERIAL NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) CREATE TABLE acl_object_identities (id SERIAL NOT NULL, parent_object_identity_id INT DEFAULT NULL, class_id INT NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id) CREATE TABLE acl_object_identity_ancestors (object_identity_id INT NOT NULL, ancestor_id INT NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id)) CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id) CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id) CREATE TABLE acl_entries (id SERIAL NOT NULL, class_id INT NOT NULL, object_identity_id INT DEFAULT NULL, security_identity_id INT NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT NOT NULL, mask INT NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id) CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id) CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id) CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id) ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) NOT DEFERRABLE INITIALLY IMMEDIATE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATEPK]d(Security/Acl/Resources/schema/sqlite.sqlnu[CREATE TABLE acl_classes (id INTEGER NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY("id")) CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) CREATE TABLE acl_security_identities (id INTEGER NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, PRIMARY KEY("id")) CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) CREATE TABLE acl_object_identities (id INTEGER NOT NULL, parent_object_identity_id INTEGER DEFAULT NULL, class_id INTEGER NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, PRIMARY KEY("id")) CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id) CREATE TABLE acl_object_identity_ancestors (object_identity_id INTEGER NOT NULL, ancestor_id INTEGER NOT NULL, PRIMARY KEY("object_identity_id", "ancestor_id")) CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id) CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id) CREATE TABLE acl_entries (id INTEGER NOT NULL, class_id INTEGER NOT NULL, object_identity_id INTEGER DEFAULT NULL, security_identity_id INTEGER NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order INTEGER NOT NULL, mask INTEGER NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, PRIMARY KEY("id")) CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id) CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id) CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id) CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)PK]j~ cF F %Security/Acl/Resources/schema/db2.sqlnu[CREATE TABLE acl_classes (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) CREATE TABLE acl_security_identities (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, identifier VARCHAR(200) NOT NULL, username SMALLINT NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) CREATE TABLE acl_object_identities (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, parent_object_identity_id INTEGER DEFAULT NULL, class_id INTEGER NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting SMALLINT NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id) CREATE TABLE acl_object_identity_ancestors (object_identity_id INTEGER NOT NULL, ancestor_id INTEGER NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id)) CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id) CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id) CREATE TABLE acl_entries (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, class_id INTEGER NOT NULL, object_identity_id INTEGER DEFAULT NULL, security_identity_id INTEGER NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT NOT NULL, mask INTEGER NOT NULL, granting SMALLINT NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success SMALLINT NOT NULL, audit_failure SMALLINT NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id) CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id) CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id) CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id) ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK]#~~*Security/Acl/Resources/bin/generateSql.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ require_once __DIR__.'/../../../../ClassLoader/ClassLoader.php'; use Symfony\Component\ClassLoader\ClassLoader; use Symfony\Component\Finder\Finder; use Symfony\Component\Security\Acl\Dbal\Schema; $loader = new ClassLoader(); $loader->addPrefixes(array( 'Symfony' => __DIR__.'/../../../../../..', 'Doctrine\\Common' => __DIR__.'/../../../../../../../vendor/doctrine-common/lib', 'Doctrine\\DBAL\\Migrations' => __DIR__.'/../../../../../../../vendor/doctrine-migrations/lib', 'Doctrine\\DBAL' => __DIR__.'/../../../../../../../vendor/doctrine-dbal/lib', 'Doctrine' => __DIR__.'/../../../../../../../vendor/doctrine/lib', )); $loader->register(); $schema = new Schema(array( 'class_table_name' => 'acl_classes', 'entry_table_name' => 'acl_entries', 'oid_table_name' => 'acl_object_identities', 'oid_ancestors_table_name' => 'acl_object_identity_ancestors', 'sid_table_name' => 'acl_security_identities', )); $reflection = new ReflectionClass('Doctrine\\DBAL\\Platforms\\AbstractPlatform'); $finder = new Finder(); $finder->name('*Platform.php')->in(dirname($reflection->getFileName())); foreach ($finder as $file) { require_once $file->getPathName(); $className = 'Doctrine\\DBAL\\Platforms\\'.$file->getBasename('.php'); $reflection = new ReflectionClass($className); if ($reflection->isAbstract()) { continue; } $platform = $reflection->newInstance(); $targetFile = sprintf(__DIR__.'/../schema/%s.sql', $platform->name); file_put_contents($targetFile, implode("\n\n", $schema->toSql($platform))); } PK]W}?Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Retrieves the object identity for a given domain object * * @author Johannes M. Schmitt */ interface ObjectIdentityRetrievalStrategyInterface { /** * Retrieves the object identity from a domain object * * @param object $domainObject * @return ObjectIdentityInterface */ public function getObjectIdentity($domainObject); } PK]ݤUU*Security/Acl/Model/FieldEntryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Interface for entries which are restricted to specific fields * * @author Johannes M. Schmitt */ interface FieldEntryInterface extends EntryInterface { /** * Returns the field used for this entry. * * @return string */ public function getField(); } PK]#(Security/Acl/Model/AclCacheInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * AclCache Interface * * @author Johannes M. Schmitt */ interface AclCacheInterface { /** * Removes an ACL from the cache * * @param string $primaryKey a serialized primary key */ public function evictFromCacheById($primaryKey); /** * Removes an ACL from the cache * * The ACL which is returned, must reference the passed object identity. * * @param ObjectIdentityInterface $oid */ public function evictFromCacheByIdentity(ObjectIdentityInterface $oid); /** * Retrieves an ACL for the given object identity primary key from the cache * * @param integer $primaryKey * @return AclInterface */ public function getFromCacheById($primaryKey); /** * Retrieves an ACL for the given object identity from the cache * * @param ObjectIdentityInterface $oid * @return AclInterface */ public function getFromCacheByIdentity(ObjectIdentityInterface $oid); /** * Stores a new ACL in the cache * * @param AclInterface $acl */ public function putInCache(AclInterface $acl); /** * Removes all ACLs from the cache */ public function clearCache(); } PK]ӗ&1,Security/Acl/Model/AuditableAclInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * This interface adds auditing capabilities to the ACL. * * @author Johannes M. Schmitt */ interface AuditableAclInterface extends MutableAclInterface { /** * Updates auditing for class-based ACE * * @param integer $index * @param Boolean $auditSuccess * @param Boolean $auditFailure */ public function updateClassAuditing($index, $auditSuccess, $auditFailure); /** * Updates auditing for class-field-based ACE * * @param integer $index * @param string $field * @param Boolean $auditSuccess * @param Boolean $auditFailure */ public function updateClassFieldAuditing($index, $field, $auditSuccess, $auditFailure); /** * Updates auditing for object-based ACE * * @param integer $index * @param Boolean $auditSuccess * @param Boolean $auditFailure */ public function updateObjectAuditing($index, $auditSuccess, $auditFailure); /** * Updates auditing for object-field-based ACE * * @param integer $index * @param string $field * @param Boolean $auditSuccess * @param Boolean $auditFailure */ public function updateObjectFieldAuditing($index, $field, $auditSuccess, $auditFailure); } PK] 8FF%Security/Acl/Model/EntryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * This class represents an individual entry in the ACL list. * * Instances MUST be immutable, as they are returned by the ACL and should not * allow client modification. * * @author Johannes M. Schmitt */ interface EntryInterface extends \Serializable { /** * The ACL this ACE is associated with. * * @return AclInterface */ public function getAcl(); /** * The primary key of this ACE * * @return integer */ public function getId(); /** * The permission mask of this ACE * * @return integer */ public function getMask(); /** * The security identity associated with this ACE * * @return SecurityIdentityInterface */ public function getSecurityIdentity(); /** * The strategy for comparing masks * * @return string */ public function getStrategy(); /** * Returns whether this ACE is granting, or denying * * @return Boolean */ public function isGranting(); } PK]t .Security/Acl/Model/AuditableEntryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * ACEs can implement this interface if they support auditing capabilities. * * @author Johannes M. Schmitt */ interface AuditableEntryInterface extends EntryInterface { /** * Whether auditing for successful grants is turned on * * @return Boolean */ public function isAuditFailure(); /** * Whether auditing for successful denies is turned on * * @return Boolean */ public function isAuditSuccess(); } PK]770Security/Acl/Model/SecurityIdentityInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * This interface provides an additional level of indirection, so that * we can work with abstracted versions of security objects and do * not have to save the entire objects. * * @author Johannes M. Schmitt */ interface SecurityIdentityInterface { /** * This method is used to compare two security identities in order to * not rely on referential equality. * * @param SecurityIdentityInterface $identity */ public function equals(SecurityIdentityInterface $identity); } PK]H * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Interface for audit loggers * * @author Johannes M. Schmitt */ interface AuditLoggerInterface { /** * This method is called whenever access is granted, or denied, and * administrative mode is turned off. * * @param Boolean $granted * @param EntryInterface $ace */ public function logIfNeeded($granted, EntryInterface $ace); } PK]-癥:Security/Acl/Model/PermissionGrantingStrategyInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Interface used by permission granting implementations. * * @author Johannes M. Schmitt */ interface PermissionGrantingStrategyInterface { /** * Determines whether access to a domain object is to be granted * * @param AclInterface $acl * @param array $masks * @param array $sids * @param Boolean $administrativeMode * @return Boolean */ public function isGranted(AclInterface $acl, array $masks, array $sids, $administrativeMode = false); /** * Determines whether access to a domain object's field is to be granted * * @param AclInterface $acl * @param string $field * @param array $masks * @param array $sids * @param Boolean $administrativeMode * * @return Boolean */ public function isFieldGranted(AclInterface $acl, $field, array $masks, array $sids, $administrativeMode = false); } PK][Ob3ASecurity/Acl/Model/SecurityIdentityRetrievalStrategyInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * Interface for retrieving security identities from tokens * * @author Johannes M. Schmitt */ interface SecurityIdentityRetrievalStrategyInterface { /** * Retrieves the available security identities for the given token * * The order in which the security identities are returned is significant. * Typically, security identities should be ordered from most specific to * least specific. * * @param TokenInterface $token * * @return SecurityIdentityInterface[] An array of SecurityIdentityInterface implementations */ public function getSecurityIdentities(TokenInterface $token); } PK]6*Security/Acl/Model/MutableAclInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * This interface adds mutators for the AclInterface. * * All changes to Access Control Entries must go through this interface. Access * Control Entries must never be modified directly. * * @author Johannes M. Schmitt */ interface MutableAclInterface extends AclInterface { /** * Deletes a class-based ACE * * @param integer $index */ public function deleteClassAce($index); /** * Deletes a class-field-based ACE * * @param integer $index * @param string $field */ public function deleteClassFieldAce($index, $field); /** * Deletes an object-based ACE * * @param integer $index */ public function deleteObjectAce($index); /** * Deletes an object-field-based ACE * * @param integer $index * @param string $field */ public function deleteObjectFieldAce($index, $field); /** * Returns the primary key of this ACL * * @return integer */ public function getId(); /** * Inserts a class-based ACE * * @param SecurityIdentityInterface $sid * @param integer $mask * @param integer $index * @param Boolean $granting * @param string $strategy */ public function insertClassAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Inserts a class-field-based ACE * * @param string $field * @param SecurityIdentityInterface $sid * @param integer $mask * @param integer $index * @param Boolean $granting * @param string $strategy */ public function insertClassFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Inserts an object-based ACE * * @param SecurityIdentityInterface $sid * @param integer $mask * @param integer $index * @param Boolean $granting * @param string $strategy */ public function insertObjectAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Inserts an object-field-based ACE * * @param string $field * @param SecurityIdentityInterface $sid * @param integer $mask * @param integer $index * @param Boolean $granting * @param string $strategy */ public function insertObjectFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Sets whether entries are inherited * * @param Boolean $boolean */ public function setEntriesInheriting($boolean); /** * Sets the parent ACL * * @param AclInterface|null $acl */ public function setParentAcl(AclInterface $acl = null); /** * Updates a class-based ACE * * @param integer $index * @param integer $mask * @param string $strategy if null the strategy should not be changed */ public function updateClassAce($index, $mask, $strategy = null); /** * Updates a class-field-based ACE * * @param integer $index * @param string $field * @param integer $mask * @param string $strategy if null the strategy should not be changed */ public function updateClassFieldAce($index, $field, $mask, $strategy = null); /** * Updates an object-based ACE * * @param integer $index * @param integer $mask * @param string $strategy if null the strategy should not be changed */ public function updateObjectAce($index, $mask, $strategy = null); /** * Updates an object-field-based ACE * * @param integer $index * @param string $field * @param integer $mask * @param string $strategy if null the strategy should not be changed */ public function updateObjectFieldAce($index, $field, $mask, $strategy = null); } PK]𕛼 #Security/Acl/Model/AclInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; use Symfony\Component\Security\Acl\Exception\NoAceFoundException; /** * This interface represents an access control list (ACL) for a domain object. * Each domain object can have exactly one associated ACL. * * An ACL contains all access control entries (ACE) for a given domain object. * In order to avoid needing references to the domain object itself, implementations * use ObjectIdentity implementations as an additional level of indirection. * * @author Johannes M. Schmitt */ interface AclInterface extends \Serializable { /** * Returns all class-based ACEs associated with this ACL * * @return array */ public function getClassAces(); /** * Returns all class-field-based ACEs associated with this ACL * * @param string $field * @return array */ public function getClassFieldAces($field); /** * Returns all object-based ACEs associated with this ACL * * @return array */ public function getObjectAces(); /** * Returns all object-field-based ACEs associated with this ACL * * @param string $field * @return array */ public function getObjectFieldAces($field); /** * Returns the object identity associated with this ACL * * @return ObjectIdentityInterface */ public function getObjectIdentity(); /** * Returns the parent ACL, or null if there is none. * * @return AclInterface|null */ public function getParentAcl(); /** * Whether this ACL is inheriting ACEs from a parent ACL. * * @return Boolean */ public function isEntriesInheriting(); /** * Determines whether field access is granted * * @param string $field * @param array $masks * @param array $securityIdentities * @param Boolean $administrativeMode * @return Boolean */ public function isFieldGranted($field, array $masks, array $securityIdentities, $administrativeMode = false); /** * Determines whether access is granted * * @throws NoAceFoundException when no ACE was applicable for this request * @param array $masks * @param array $securityIdentities * @param Boolean $administrativeMode * @return Boolean */ public function isGranted(array $masks, array $securityIdentities, $administrativeMode = false); /** * Whether the ACL has loaded ACEs for all of the passed security identities * * @param mixed $securityIdentities an implementation of SecurityIdentityInterface, or an array thereof * @return Boolean */ public function isSidLoaded($securityIdentities); } PK]5Ayy.Security/Acl/Model/ObjectIdentityInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Represents the identity of an individual domain object instance. * * @author Johannes M. Schmitt */ interface ObjectIdentityInterface { /** * We specifically require this method so we can check for object equality * explicitly, and do not have to rely on referencial equality instead. * * Though in most cases, both checks should result in the same outcome. * * Referential Equality: $object1 === $object2 * Example for Object Equality: $object1->getId() === $object2->getId() * * @param ObjectIdentityInterface $identity * @return Boolean */ public function equals(ObjectIdentityInterface $identity); /** * Obtains a unique identifier for this object. The identifier must not be * re-used for other objects with the same type. * * @return string cannot return null */ public function getIdentifier(); /** * Returns a type for the domain object. Typically, this is the PHP class name. * * @return string cannot return null */ public function getType(); } PK]j2Security/Acl/Model/MutableAclProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Provides support for creating and storing ACL instances. * * @author Johannes M. Schmitt */ interface MutableAclProviderInterface extends AclProviderInterface { /** * Creates a new ACL for the given object identity. * * @throws AclAlreadyExistsException when there already is an ACL for the given * object identity * @param ObjectIdentityInterface $oid * @return MutableAclInterface */ public function createAcl(ObjectIdentityInterface $oid); /** * Deletes the ACL for a given object identity. * * This will automatically trigger a delete for any child ACLs. If you don't * want child ACLs to be deleted, you will have to set their parent ACL to null. * * @param ObjectIdentityInterface $oid */ public function deleteAcl(ObjectIdentityInterface $oid); /** * Persists any changes which were made to the ACL, or any associated * access control entries. * * Changes to parent ACLs are not persisted. * * @param MutableAclInterface $acl */ public function updateAcl(MutableAclInterface $acl); } PK]X ,Security/Acl/Model/DomainObjectInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * This method can be implemented by domain objects which you want to store * ACLs for if they do not have a getId() method, or getId() does not return * a unique identifier. * * @author Johannes M. Schmitt */ interface DomainObjectInterface { /** * Returns a unique identifier for this domain object. * * @return string */ public function getObjectIdentifier(); } PK]+Security/Acl/Model/AclProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; use Symfony\Component\Security\Acl\Exception\AclNotFoundException; /** * Provides a common interface for retrieving ACLs. * * @author Johannes M. Schmitt */ interface AclProviderInterface { /** * Retrieves all child object identities from the database * * @param ObjectIdentityInterface $parentOid * @param Boolean $directChildrenOnly * * @return array returns an array of child 'ObjectIdentity's */ public function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false); /** * Returns the ACL that belongs to the given object identity * * @param ObjectIdentityInterface $oid * @param SecurityIdentityInterface[] $sids * * @return AclInterface * * @throws AclNotFoundException when there is no ACL */ public function findAcl(ObjectIdentityInterface $oid, array $sids = array()); /** * Returns the ACLs that belong to the given object identities * * @param ObjectIdentityInterface[] $oids an array of ObjectIdentityInterface implementations * @param SecurityIdentityInterface[] $sids an array of SecurityIdentityInterface implementations * * @return \SplObjectStorage mapping the passed object identities to ACLs * * @throws AclNotFoundException when we cannot find an ACL for all identities */ public function findAcls(array $oids, array $sids = array()); } PK]epgg'Security/Acl/Permission/MaskBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Permission; /** * This class allows you to build cumulative permissions easily, or convert * masks to a human-readable format. * * * $builder = new MaskBuilder(); * $builder * ->add('view') * ->add('create') * ->add('edit') * ; * var_dump($builder->get()); // int(7) * var_dump($builder->getPattern()); // string(32) ".............................ECV" * * * We have defined some commonly used base permissions which you can use: * - VIEW: the SID is allowed to view the domain object / field * - CREATE: the SID is allowed to create new instances of the domain object / fields * - EDIT: the SID is allowed to edit existing instances of the domain object / field * - DELETE: the SID is allowed to delete domain objects * - UNDELETE: the SID is allowed to recover domain objects from trash * - OPERATOR: the SID is allowed to perform any action on the domain object * except for granting others permissions * - MASTER: the SID is allowed to perform any action on the domain object, * and is allowed to grant other SIDs any permission except for * MASTER and OWNER permissions * - OWNER: the SID is owning the domain object in question and can perform any * action on the domain object as well as grant any permission * * @author Johannes M. Schmitt */ class MaskBuilder { const MASK_VIEW = 1; // 1 << 0 const MASK_CREATE = 2; // 1 << 1 const MASK_EDIT = 4; // 1 << 2 const MASK_DELETE = 8; // 1 << 3 const MASK_UNDELETE = 16; // 1 << 4 const MASK_OPERATOR = 32; // 1 << 5 const MASK_MASTER = 64; // 1 << 6 const MASK_OWNER = 128; // 1 << 7 const MASK_IDDQD = 1073741823; // 1 << 0 | 1 << 1 | ... | 1 << 30 const CODE_VIEW = 'V'; const CODE_CREATE = 'C'; const CODE_EDIT = 'E'; const CODE_DELETE = 'D'; const CODE_UNDELETE = 'U'; const CODE_OPERATOR = 'O'; const CODE_MASTER = 'M'; const CODE_OWNER = 'N'; const ALL_OFF = '................................'; const OFF = '.'; const ON = '*'; private $mask; /** * Constructor * * @param integer $mask optional; defaults to 0 * * @throws \InvalidArgumentException */ public function __construct($mask = 0) { if (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } $this->mask = $mask; } /** * Adds a mask to the permission * * @param mixed $mask * * @return MaskBuilder * * @throws \InvalidArgumentException */ public function add($mask) { if (is_string($mask) && defined($name = 'static::MASK_'.strtoupper($mask))) { $mask = constant($name); } elseif (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } $this->mask |= $mask; return $this; } /** * Returns the mask of this permission * * @return integer */ public function get() { return $this->mask; } /** * Returns a human-readable representation of the permission * * @return string */ public function getPattern() { $pattern = self::ALL_OFF; $length = strlen($pattern); $bitmask = str_pad(decbin($this->mask), $length, '0', STR_PAD_LEFT); for ($i=$length-1; $i>=0; $i--) { if ('1' === $bitmask[$i]) { try { $pattern[$i] = self::getCode(1 << ($length - $i - 1)); } catch (\Exception $notPredefined) { $pattern[$i] = self::ON; } } } return $pattern; } /** * Removes a mask from the permission * * @param mixed $mask * * @return MaskBuilder * * @throws \InvalidArgumentException */ public function remove($mask) { if (is_string($mask) && defined($name = 'static::MASK_'.strtoupper($mask))) { $mask = constant($name); } elseif (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } $this->mask &= ~$mask; return $this; } /** * Resets the PermissionBuilder * * @return MaskBuilder */ public function reset() { $this->mask = 0; return $this; } /** * Returns the code for the passed mask * * @param integer $mask * @throws \InvalidArgumentException * @throws \RuntimeException * @return string */ public static function getCode($mask) { if (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } $reflection = new \ReflectionClass(get_called_class()); foreach ($reflection->getConstants() as $name => $cMask) { if (0 !== strpos($name, 'MASK_')) { continue; } if ($mask === $cMask) { if (!defined($cName = 'static::CODE_'.substr($name, 5))) { throw new \RuntimeException('There was no code defined for this mask.'); } return constant($cName); } } throw new \InvalidArgumentException(sprintf('The mask "%d" is not supported.', $mask)); } } PK] c0 .Security/Acl/Permission/BasicPermissionMap.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Permission; /** * This is basic permission map complements the masks which have been defined * on the standard implementation of the MaskBuilder. * * @author Johannes M. Schmitt */ class BasicPermissionMap implements PermissionMapInterface { const PERMISSION_VIEW = 'VIEW'; const PERMISSION_EDIT = 'EDIT'; const PERMISSION_CREATE = 'CREATE'; const PERMISSION_DELETE = 'DELETE'; const PERMISSION_UNDELETE = 'UNDELETE'; const PERMISSION_OPERATOR = 'OPERATOR'; const PERMISSION_MASTER = 'MASTER'; const PERMISSION_OWNER = 'OWNER'; protected $map; public function __construct() { $this->map = array( self::PERMISSION_VIEW => array( MaskBuilder::MASK_VIEW, MaskBuilder::MASK_EDIT, MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_EDIT => array( MaskBuilder::MASK_EDIT, MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_CREATE => array( MaskBuilder::MASK_CREATE, MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_DELETE => array( MaskBuilder::MASK_DELETE, MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_UNDELETE => array( MaskBuilder::MASK_UNDELETE, MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_OPERATOR => array( MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_MASTER => array( MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_OWNER => array( MaskBuilder::MASK_OWNER, ), ); } /** * {@inheritDoc} */ public function getMasks($permission, $object) { if (!isset($this->map[$permission])) { return null; } return $this->map[$permission]; } /** * {@inheritDoc} */ public function contains($permission) { return isset($this->map[$permission]); } } PK]w2Security/Acl/Permission/PermissionMapInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Permission; /** * This is the interface that must be implemented by permission maps. * * @author Johannes M. Schmitt */ interface PermissionMapInterface { /** * Returns an array of bitmasks. * * The security identity must have been granted access to at least one of * these bitmasks. * * @param string $permission * @param object $object * @return array may return null if permission/object combination is not supported */ public function getMasks($permission, $object); /** * Whether this map contains the given permission * * @param string $permission * @return Boolean */ public function contains($permission); } PK]P͡/Security/Acl/Exception/AclNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when we cannot locate an ACL for a passed * ObjectIdentity implementation. * * @author Johannes M. Schmitt */ class AclNotFoundException extends Exception { } PK]W:Security/Acl/Exception/ConcurrentModificationException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown whenever you change shared properties of more than * one ACL of the same class type concurrently. * * @author Johannes M. Schmitt */ class ConcurrentModificationException extends Exception { } PK]Bl.Security/Acl/Exception/NoAceFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when we cannot locate an ACE that matches the * combination of permission masks and security identities. * * @author Johannes M. Schmitt */ class NoAceFoundException extends Exception { public function __construct() { parent::__construct('No applicable ACE was found.'); } } PK]kq$Security/Acl/Exception/Exception.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * Base ACL exception * * @author Johannes M. Schmitt */ class Exception extends \Exception { } PK][z0Security/Acl/Exception/SidNotLoadedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when ACEs for an SID are requested which has not * been loaded from the database. * * @author Johannes M. Schmitt */ class SidNotLoadedException extends Exception { } PK]5  4Security/Acl/Exception/AclAlreadyExistsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when someone tries to create an ACL for an object * identity that already has one. * * @author Johannes M. Schmitt */ class AclAlreadyExistsException extends Exception { } PK]]_""3Security/Acl/Exception/NotAllAclsFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when you have requested ACLs for multiple object * identities, but the AclProvider implementation failed to find ACLs for all * identities. * * This exception contains the partial result. * * @author Johannes M. Schmitt */ class NotAllAclsFoundException extends AclNotFoundException { private $partialResult; /** * Sets the partial result * * @param \SplObjectStorage $result */ public function setPartialResult(\SplObjectStorage $result) { $this->partialResult = $result; } /** * Returns the partial result * * @return \SplObjectStorage */ public function getPartialResult() { return $this->partialResult; } } PK]O7Security/Acl/Exception/InvalidDomainObjectException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when ObjectIdentity fails to construct an object * identity from the passed domain object. * * @author Johannes M. Schmitt */ class InvalidDomainObjectException extends Exception { } PK]^+f+f!Security/Acl/Dbal/AclProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Dbal; use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\Statement; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Domain\Acl; use Symfony\Component\Security\Acl\Domain\Entry; use Symfony\Component\Security\Acl\Domain\FieldEntry; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Exception\AclNotFoundException; use Symfony\Component\Security\Acl\Exception\NotAllAclsFoundException; use Symfony\Component\Security\Acl\Model\AclCacheInterface; use Symfony\Component\Security\Acl\Model\AclProviderInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface; /** * An ACL provider implementation. * * This provider assumes that all ACLs share the same PermissionGrantingStrategy. * * @author Johannes M. Schmitt */ class AclProvider implements AclProviderInterface { const MAX_BATCH_SIZE = 30; protected $cache; protected $connection; protected $loadedAces = array(); protected $loadedAcls = array(); protected $options; private $permissionGrantingStrategy; /** * Constructor. * * @param Connection $connection * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy * @param array $options * @param AclCacheInterface $cache */ public function __construct(Connection $connection, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $options, AclCacheInterface $cache = null) { $this->cache = $cache; $this->connection = $connection; $this->options = $options; $this->permissionGrantingStrategy = $permissionGrantingStrategy; } /** * {@inheritDoc} */ public function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false) { $sql = $this->getFindChildrenSql($parentOid, $directChildrenOnly); $children = array(); foreach ($this->connection->executeQuery($sql)->fetchAll() as $data) { $children[] = new ObjectIdentity($data['object_identifier'], $data['class_type']); } return $children; } /** * {@inheritDoc} */ public function findAcl(ObjectIdentityInterface $oid, array $sids = array()) { return $this->findAcls(array($oid), $sids)->offsetGet($oid); } /** * {@inheritDoc} */ public function findAcls(array $oids, array $sids = array()) { $result = new \SplObjectStorage(); $currentBatch = array(); $oidLookup = array(); for ($i=0,$c=count($oids); $i<$c; $i++) { $oid = $oids[$i]; $oidLookupKey = $oid->getIdentifier().$oid->getType(); $oidLookup[$oidLookupKey] = $oid; $aclFound = false; // check if result already contains an ACL if ($result->contains($oid)) { $aclFound = true; } // check if this ACL has already been hydrated if (!$aclFound && isset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()])) { $acl = $this->loadedAcls[$oid->getType()][$oid->getIdentifier()]; if (!$acl->isSidLoaded($sids)) { // FIXME: we need to load ACEs for the missing SIDs. This is never // reached by the default implementation, since we do not // filter by SID throw new \RuntimeException('This is not supported by the default implementation.'); } else { $result->attach($oid, $acl); $aclFound = true; } } // check if we can locate the ACL in the cache if (!$aclFound && null !== $this->cache) { $acl = $this->cache->getFromCacheByIdentity($oid); if (null !== $acl) { if ($acl->isSidLoaded($sids)) { // check if any of the parents has been loaded since we need to // ensure that there is only ever one ACL per object identity $parentAcl = $acl->getParentAcl(); while (null !== $parentAcl) { $parentOid = $parentAcl->getObjectIdentity(); if (isset($this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()])) { $acl->setParentAcl($this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()]); break; } else { $this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()] = $parentAcl; $this->updateAceIdentityMap($parentAcl); } $parentAcl = $parentAcl->getParentAcl(); } $this->loadedAcls[$oid->getType()][$oid->getIdentifier()] = $acl; $this->updateAceIdentityMap($acl); $result->attach($oid, $acl); $aclFound = true; } else { $this->cache->evictFromCacheByIdentity($oid); foreach ($this->findChildren($oid) as $childOid) { $this->cache->evictFromCacheByIdentity($childOid); } } } } // looks like we have to load the ACL from the database if (!$aclFound) { $currentBatch[] = $oid; } // Is it time to load the current batch? if ((self::MAX_BATCH_SIZE === count($currentBatch) || ($i + 1) === $c) && count($currentBatch) > 0) { try { $loadedBatch = $this->lookupObjectIdentities($currentBatch, $sids, $oidLookup); } catch (AclNotFoundException $aclNotFoundexception) { if ($result->count()) { $partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.'); $partialResultException->setPartialResult($result); throw $partialResultException; } else { throw $aclNotFoundexception; } } foreach ($loadedBatch as $loadedOid) { $loadedAcl = $loadedBatch->offsetGet($loadedOid); if (null !== $this->cache) { $this->cache->putInCache($loadedAcl); } if (isset($oidLookup[$loadedOid->getIdentifier().$loadedOid->getType()])) { $result->attach($loadedOid, $loadedAcl); } } $currentBatch = array(); } } // check that we got ACLs for all the identities foreach ($oids as $oid) { if (!$result->contains($oid)) { if (1 === count($oids)) { throw new AclNotFoundException(sprintf('No ACL found for %s.', $oid)); } $partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.'); $partialResultException->setPartialResult($result); throw $partialResultException; } } return $result; } /** * Constructs the query used for looking up object identities and associated * ACEs, and security identities. * * @param array $ancestorIds * @return string */ protected function getLookupSql(array $ancestorIds) { // FIXME: add support for filtering by sids (right now we select all sids) $sql = <<options['oid_table_name']} o INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id LEFT JOIN {$this->options['entry_table_name']} e ON ( e.class_id = o.class_id AND (e.object_identity_id = o.id OR {$this->connection->getDatabasePlatform()->getIsNullExpression('e.object_identity_id')}) ) LEFT JOIN {$this->options['sid_table_name']} s ON ( s.id = e.security_identity_id ) WHERE (o.id = SELECTCLAUSE; $sql .= implode(' OR o.id = ', $ancestorIds).')'; return $sql; } protected function getAncestorLookupSql(array $batch) { $sql = <<options['oid_table_name']} o INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id INNER JOIN {$this->options['oid_ancestors_table_name']} a ON a.object_identity_id = o.id WHERE ( SELECTCLAUSE; $types = array(); $count = count($batch); for ($i = 0; $i < $count; $i++) { if (!isset($types[$batch[$i]->getType()])) { $types[$batch[$i]->getType()] = true; // if there is more than one type we can safely break out of the // loop, because it is the differentiator factor on whether to // query for only one or more class types if (count($types) > 1) { break; } } } if (1 === count($types)) { $ids = array(); for ($i = 0; $i < $count; $i++) { $ids[] = $this->connection->quote($batch[$i]->getIdentifier()); } $sql .= sprintf( '(o.object_identifier IN (%s) AND c.class_type = %s)', implode(',', $ids), $this->connection->quote($batch[0]->getType()) ); } else { $where = '(o.object_identifier = %s AND c.class_type = %s)'; for ($i = 0; $i < $count; $i++) { $sql .= sprintf( $where, $this->connection->quote($batch[$i]->getIdentifier()), $this->connection->quote($batch[$i]->getType()) ); if ($i+1 < $count) { $sql .= ' OR '; } } } $sql .= ')'; return $sql; } /** * Constructs the SQL for retrieving child object identities for the given * object identities. * * @param ObjectIdentityInterface $oid * @param Boolean $directChildrenOnly * @return string */ protected function getFindChildrenSql(ObjectIdentityInterface $oid, $directChildrenOnly) { if (false === $directChildrenOnly) { $query = <<options['oid_table_name']} as o INNER JOIN {$this->options['class_table_name']} as c ON c.id = o.class_id INNER JOIN {$this->options['oid_ancestors_table_name']} as a ON a.object_identity_id = o.id WHERE a.ancestor_id = %d AND a.object_identity_id != a.ancestor_id FINDCHILDREN; } else { $query = <<options['oid_table_name']} as o INNER JOIN {$this->options['class_table_name']} as c ON c.id = o.class_id WHERE o.parent_object_identity_id = %d FINDCHILDREN; } return sprintf($query, $this->retrieveObjectIdentityPrimaryKey($oid)); } /** * Constructs the SQL for retrieving the primary key of the given object * identity. * * @param ObjectIdentityInterface $oid * @return string */ protected function getSelectObjectIdentityIdSql(ObjectIdentityInterface $oid) { $query = <<options['oid_table_name'], $this->options['class_table_name'], $this->connection->quote($oid->getIdentifier()), $this->connection->quote($oid->getType()) ); } /** * Returns the primary key of the passed object identity. * * @param ObjectIdentityInterface $oid * @return integer */ final protected function retrieveObjectIdentityPrimaryKey(ObjectIdentityInterface $oid) { return $this->connection->executeQuery($this->getSelectObjectIdentityIdSql($oid))->fetchColumn(); } /** * This method is called when an ACL instance is retrieved from the cache. * * @param AclInterface $acl */ private function updateAceIdentityMap(AclInterface $acl) { foreach (array('classAces', 'classFieldAces', 'objectAces', 'objectFieldAces') as $property) { $reflection = new \ReflectionProperty($acl, $property); $reflection->setAccessible(true); $value = $reflection->getValue($acl); if ('classAces' === $property || 'objectAces' === $property) { $this->doUpdateAceIdentityMap($value); } else { foreach ($value as $field => $aces) { $this->doUpdateAceIdentityMap($value[$field]); } } $reflection->setValue($acl, $value); $reflection->setAccessible(false); } } /** * Retrieves all the ids which need to be queried from the database * including the ids of parent ACLs. * * @param array $batch * * @return array */ private function getAncestorIds(array $batch) { $sql = $this->getAncestorLookupSql($batch); $ancestorIds = array(); foreach ($this->connection->executeQuery($sql)->fetchAll() as $data) { // FIXME: skip ancestors which are cached $ancestorIds[] = $data['ancestor_id']; } return $ancestorIds; } /** * Does either overwrite the passed ACE, or saves it in the global identity * map to ensure every ACE only gets instantiated once. * * @param array &$aces */ private function doUpdateAceIdentityMap(array &$aces) { foreach ($aces as $index => $ace) { if (isset($this->loadedAces[$ace->getId()])) { $aces[$index] = $this->loadedAces[$ace->getId()]; } else { $this->loadedAces[$ace->getId()] = $ace; } } } /** * This method is called for object identities which could not be retrieved * from the cache, and for which thus a database query is required. * * @param array $batch * @param array $sids * @param array $oidLookup * * @return \SplObjectStorage mapping object identities to ACL instances * * @throws AclNotFoundException */ private function lookupObjectIdentities(array $batch, array $sids, array $oidLookup) { $ancestorIds = $this->getAncestorIds($batch); if (!$ancestorIds) { throw new AclNotFoundException('There is no ACL for the given object identity.'); } $sql = $this->getLookupSql($ancestorIds); $stmt = $this->connection->executeQuery($sql); return $this->hydrateObjectIdentities($stmt, $oidLookup, $sids); } /** * This method is called to hydrate ACLs and ACEs. * * This method was designed for performance; thus, a lot of code has been * inlined at the cost of readability, and maintainability. * * Keep in mind that changes to this method might severely reduce the * performance of the entire ACL system. * * @param Statement $stmt * @param array $oidLookup * @param array $sids * @throws \RuntimeException * @return \SplObjectStorage */ private function hydrateObjectIdentities(Statement $stmt, array $oidLookup, array $sids) { $parentIdToFill = new \SplObjectStorage(); $acls = $aces = $emptyArray = array(); $oidCache = $oidLookup; $result = new \SplObjectStorage(); $loadedAces =& $this->loadedAces; $loadedAcls =& $this->loadedAcls; $permissionGrantingStrategy = $this->permissionGrantingStrategy; // we need these to set protected properties on hydrated objects $aclReflection = new \ReflectionClass('Symfony\Component\Security\Acl\Domain\Acl'); $aclClassAcesProperty = $aclReflection->getProperty('classAces'); $aclClassAcesProperty->setAccessible(true); $aclClassFieldAcesProperty = $aclReflection->getProperty('classFieldAces'); $aclClassFieldAcesProperty->setAccessible(true); $aclObjectAcesProperty = $aclReflection->getProperty('objectAces'); $aclObjectAcesProperty->setAccessible(true); $aclObjectFieldAcesProperty = $aclReflection->getProperty('objectFieldAces'); $aclObjectFieldAcesProperty->setAccessible(true); $aclParentAclProperty = $aclReflection->getProperty('parentAcl'); $aclParentAclProperty->setAccessible(true); // fetchAll() consumes more memory than consecutive calls to fetch(), // but it is faster foreach ($stmt->fetchAll(\PDO::FETCH_NUM) as $data) { list($aclId, $objectIdentifier, $parentObjectIdentityId, $entriesInheriting, $classType, $aceId, $objectIdentityId, $fieldName, $aceOrder, $mask, $granting, $grantingStrategy, $auditSuccess, $auditFailure, $username, $securityIdentifier) = $data; // has the ACL been hydrated during this hydration cycle? if (isset($acls[$aclId])) { $acl = $acls[$aclId]; // has the ACL been hydrated during any previous cycle, or was possibly loaded // from cache? } elseif (isset($loadedAcls[$classType][$objectIdentifier])) { $acl = $loadedAcls[$classType][$objectIdentifier]; // keep reference in local array (saves us some hash calculations) $acls[$aclId] = $acl; // attach ACL to the result set; even though we do not enforce that every // object identity has only one instance, we must make sure to maintain // referential equality with the oids passed to findAcls() if (!isset($oidCache[$objectIdentifier.$classType])) { $oidCache[$objectIdentifier.$classType] = $acl->getObjectIdentity(); } $result->attach($oidCache[$objectIdentifier.$classType], $acl); // so, this hasn't been hydrated yet } else { // create object identity if we haven't done so yet $oidLookupKey = $objectIdentifier.$classType; if (!isset($oidCache[$oidLookupKey])) { $oidCache[$oidLookupKey] = new ObjectIdentity($objectIdentifier, $classType); } $acl = new Acl((integer) $aclId, $oidCache[$oidLookupKey], $permissionGrantingStrategy, $emptyArray, !!$entriesInheriting); // keep a local, and global reference to this ACL $loadedAcls[$classType][$objectIdentifier] = $acl; $acls[$aclId] = $acl; // try to fill in parent ACL, or defer until all ACLs have been hydrated if (null !== $parentObjectIdentityId) { if (isset($acls[$parentObjectIdentityId])) { $aclParentAclProperty->setValue($acl, $acls[$parentObjectIdentityId]); } else { $parentIdToFill->attach($acl, $parentObjectIdentityId); } } $result->attach($oidCache[$oidLookupKey], $acl); } // check if this row contains an ACE record if (null !== $aceId) { // have we already hydrated ACEs for this ACL? if (!isset($aces[$aclId])) { $aces[$aclId] = array($emptyArray, $emptyArray, $emptyArray, $emptyArray); } // has this ACE already been hydrated during a previous cycle, or // possible been loaded from cache? // It is important to only ever have one ACE instance per actual row since // some ACEs are shared between ACL instances if (!isset($loadedAces[$aceId])) { if (!isset($sids[$key = ($username?'1':'0').$securityIdentifier])) { if ($username) { $sids[$key] = new UserSecurityIdentity( substr($securityIdentifier, 1 + $pos = strpos($securityIdentifier, '-')), substr($securityIdentifier, 0, $pos) ); } else { $sids[$key] = new RoleSecurityIdentity($securityIdentifier); } } if (null === $fieldName) { $loadedAces[$aceId] = new Entry((integer) $aceId, $acl, $sids[$key], $grantingStrategy, (integer) $mask, !!$granting, !!$auditFailure, !!$auditSuccess); } else { $loadedAces[$aceId] = new FieldEntry((integer) $aceId, $acl, $fieldName, $sids[$key], $grantingStrategy, (integer) $mask, !!$granting, !!$auditFailure, !!$auditSuccess); } } $ace = $loadedAces[$aceId]; // assign ACE to the correct property if (null === $objectIdentityId) { if (null === $fieldName) { $aces[$aclId][0][$aceOrder] = $ace; } else { $aces[$aclId][1][$fieldName][$aceOrder] = $ace; } } else { if (null === $fieldName) { $aces[$aclId][2][$aceOrder] = $ace; } else { $aces[$aclId][3][$fieldName][$aceOrder] = $ace; } } } } // We do not sort on database level since we only want certain subsets to be sorted, // and we are going to read the entire result set anyway. // Sorting on DB level increases query time by an order of magnitude while it is // almost negligible when we use PHPs array sort functions. foreach ($aces as $aclId => $aceData) { $acl = $acls[$aclId]; ksort($aceData[0]); $aclClassAcesProperty->setValue($acl, $aceData[0]); foreach (array_keys($aceData[1]) as $fieldName) { ksort($aceData[1][$fieldName]); } $aclClassFieldAcesProperty->setValue($acl, $aceData[1]); ksort($aceData[2]); $aclObjectAcesProperty->setValue($acl, $aceData[2]); foreach (array_keys($aceData[3]) as $fieldName) { ksort($aceData[3][$fieldName]); } $aclObjectFieldAcesProperty->setValue($acl, $aceData[3]); } // fill-in parent ACLs where this hasn't been done yet cause the parent ACL was not // yet available $processed = 0; foreach ($parentIdToFill as $acl) { $parentId = $parentIdToFill->offsetGet($acl); // let's see if we have already hydrated this if (isset($acls[$parentId])) { $aclParentAclProperty->setValue($acl, $acls[$parentId]); $processed += 1; continue; } } // reset reflection changes $aclClassAcesProperty->setAccessible(false); $aclClassFieldAcesProperty->setAccessible(false); $aclObjectAcesProperty->setAccessible(false); $aclObjectFieldAcesProperty->setAccessible(false); $aclParentAclProperty->setAccessible(false); // this should never be true if the database integrity hasn't been compromised if ($processed < count($parentIdToFill)) { throw new \RuntimeException('Not all parent ids were populated. This implies an integrity problem.'); } return $result; } } PK]K VSecurity/Acl/Dbal/Schema.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Dbal; use Doctrine\DBAL\Schema\Schema as BaseSchema; use Doctrine\DBAL\Connection; /** * The schema used for the ACL system. * * @author Johannes M. Schmitt */ final class Schema extends BaseSchema { protected $options; /** * Constructor * * @param array $options the names for tables * @param Connection $connection */ public function __construct(array $options, Connection $connection = null) { $schemaConfig = null === $connection ? null : $connection->getSchemaManager()->createSchemaConfig(); parent::__construct(array(), array(), $schemaConfig); $this->options = $options; $this->addClassTable(); $this->addSecurityIdentitiesTable(); $this->addObjectIdentitiesTable(); $this->addObjectIdentityAncestorsTable(); $this->addEntryTable(); } /** * Merges ACL schema with the given schema. * * @param BaseSchema $schema */ public function addToSchema(BaseSchema $schema) { foreach ($this->getTables() as $table) { $schema->_addTable($table); } foreach ($this->getSequences() as $sequence) { $schema->_addSequence($sequence); } } /** * Adds the class table to the schema */ protected function addClassTable() { $table = $this->createTable($this->options['class_table_name']); $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto')); $table->addColumn('class_type', 'string', array('length' => 200)); $table->setPrimaryKey(array('id')); $table->addUniqueIndex(array('class_type')); } /** * Adds the entry table to the schema */ protected function addEntryTable() { $table = $this->createTable($this->options['entry_table_name']); $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto')); $table->addColumn('class_id', 'integer', array('unsigned' => true)); $table->addColumn('object_identity_id', 'integer', array('unsigned' => true, 'notnull' => false)); $table->addColumn('field_name', 'string', array('length' => 50, 'notnull' => false)); $table->addColumn('ace_order', 'smallint', array('unsigned' => true)); $table->addColumn('security_identity_id', 'integer', array('unsigned' => true)); $table->addColumn('mask', 'integer'); $table->addColumn('granting', 'boolean'); $table->addColumn('granting_strategy', 'string', array('length' => 30)); $table->addColumn('audit_success', 'boolean'); $table->addColumn('audit_failure', 'boolean'); $table->setPrimaryKey(array('id')); $table->addUniqueIndex(array('class_id', 'object_identity_id', 'field_name', 'ace_order')); $table->addIndex(array('class_id', 'object_identity_id', 'security_identity_id')); $table->addForeignKeyConstraint($this->getTable($this->options['class_table_name']), array('class_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE')); $table->addForeignKeyConstraint($this->getTable($this->options['oid_table_name']), array('object_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE')); $table->addForeignKeyConstraint($this->getTable($this->options['sid_table_name']), array('security_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE')); } /** * Adds the object identity table to the schema */ protected function addObjectIdentitiesTable() { $table = $this->createTable($this->options['oid_table_name']); $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto')); $table->addColumn('class_id', 'integer', array('unsigned' => true)); $table->addColumn('object_identifier', 'string', array('length' => 100)); $table->addColumn('parent_object_identity_id', 'integer', array('unsigned' => true, 'notnull' => false)); $table->addColumn('entries_inheriting', 'boolean'); $table->setPrimaryKey(array('id')); $table->addUniqueIndex(array('object_identifier', 'class_id')); $table->addIndex(array('parent_object_identity_id')); $table->addForeignKeyConstraint($table, array('parent_object_identity_id'), array('id')); } /** * Adds the object identity relation table to the schema */ protected function addObjectIdentityAncestorsTable() { $table = $this->createTable($this->options['oid_ancestors_table_name']); $table->addColumn('object_identity_id', 'integer', array('unsigned' => true)); $table->addColumn('ancestor_id', 'integer', array('unsigned' => true)); $table->setPrimaryKey(array('object_identity_id', 'ancestor_id')); $oidTable = $this->getTable($this->options['oid_table_name']); $table->addForeignKeyConstraint($oidTable, array('object_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE')); $table->addForeignKeyConstraint($oidTable, array('ancestor_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE')); } /** * Adds the security identity table to the schema */ protected function addSecurityIdentitiesTable() { $table = $this->createTable($this->options['sid_table_name']); $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto')); $table->addColumn('identifier', 'string', array('length' => 200)); $table->addColumn('username', 'boolean'); $table->setPrimaryKey(array('id')); $table->addUniqueIndex(array('identifier', 'username')); } } PK]tŐ(Security/Acl/Dbal/MutableAclProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Dbal; use Doctrine\Common\PropertyChangedListener; use Doctrine\DBAL\Driver\Connection; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException; use Symfony\Component\Security\Acl\Exception\ConcurrentModificationException; use Symfony\Component\Security\Acl\Model\AclCacheInterface; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\EntryInterface; use Symfony\Component\Security\Acl\Model\MutableAclInterface; use Symfony\Component\Security\Acl\Model\MutableAclProviderInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * An implementation of the MutableAclProviderInterface using Doctrine DBAL. * * @author Johannes M. Schmitt */ class MutableAclProvider extends AclProvider implements MutableAclProviderInterface, PropertyChangedListener { private $propertyChanges; /** * {@inheritDoc} */ public function __construct(Connection $connection, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $options, AclCacheInterface $cache = null) { parent::__construct($connection, $permissionGrantingStrategy, $options, $cache); $this->propertyChanges = new \SplObjectStorage(); } /** * {@inheritDoc} */ public function createAcl(ObjectIdentityInterface $oid) { if (false !== $this->retrieveObjectIdentityPrimaryKey($oid)) { throw new AclAlreadyExistsException(sprintf('%s is already associated with an ACL.', $oid)); } $this->connection->beginTransaction(); try { $this->createObjectIdentity($oid); $pk = $this->retrieveObjectIdentityPrimaryKey($oid); $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $pk)); $this->connection->commit(); } catch (\Exception $failed) { $this->connection->rollBack(); throw $failed; } // re-read the ACL from the database to ensure proper caching, etc. return $this->findAcl($oid); } /** * {@inheritDoc} */ public function deleteAcl(ObjectIdentityInterface $oid) { $this->connection->beginTransaction(); try { foreach ($this->findChildren($oid, true) as $childOid) { $this->deleteAcl($childOid); } $oidPK = $this->retrieveObjectIdentityPrimaryKey($oid); $this->deleteAccessControlEntries($oidPK); $this->deleteObjectIdentityRelations($oidPK); $this->deleteObjectIdentity($oidPK); $this->connection->commit(); } catch (\Exception $failed) { $this->connection->rollBack(); throw $failed; } // evict the ACL from the in-memory identity map if (isset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()])) { $this->propertyChanges->offsetUnset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()]); unset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()]); } // evict the ACL from any caches if (null !== $this->cache) { $this->cache->evictFromCacheByIdentity($oid); } } /** * {@inheritDoc} */ public function findAcls(array $oids, array $sids = array()) { $result = parent::findAcls($oids, $sids); foreach ($result as $oid) { $acl = $result->offsetGet($oid); if (false === $this->propertyChanges->contains($acl) && $acl instanceof MutableAclInterface) { $acl->addPropertyChangedListener($this); $this->propertyChanges->attach($acl, array()); } $parentAcl = $acl->getParentAcl(); while (null !== $parentAcl) { if (false === $this->propertyChanges->contains($parentAcl) && $acl instanceof MutableAclInterface) { $parentAcl->addPropertyChangedListener($this); $this->propertyChanges->attach($parentAcl, array()); } $parentAcl = $parentAcl->getParentAcl(); } } return $result; } /** * Implementation of PropertyChangedListener * * This allows us to keep track of which values have been changed, so we don't * have to do a full introspection when ->updateAcl() is called. * * @param mixed $sender * @param string $propertyName * @param mixed $oldValue * @param mixed $newValue * * @throws \InvalidArgumentException */ public function propertyChanged($sender, $propertyName, $oldValue, $newValue) { if (!$sender instanceof MutableAclInterface && !$sender instanceof EntryInterface) { throw new \InvalidArgumentException('$sender must be an instance of MutableAclInterface, or EntryInterface.'); } if ($sender instanceof EntryInterface) { if (null === $sender->getId()) { return; } $ace = $sender; $sender = $ace->getAcl(); } else { $ace = null; } if (false === $this->propertyChanges->contains($sender)) { throw new \InvalidArgumentException('$sender is not being tracked by this provider.'); } $propertyChanges = $this->propertyChanges->offsetGet($sender); if (null === $ace) { if (isset($propertyChanges[$propertyName])) { $oldValue = $propertyChanges[$propertyName][0]; if ($oldValue === $newValue) { unset($propertyChanges[$propertyName]); } else { $propertyChanges[$propertyName] = array($oldValue, $newValue); } } else { $propertyChanges[$propertyName] = array($oldValue, $newValue); } } else { if (!isset($propertyChanges['aces'])) { $propertyChanges['aces'] = new \SplObjectStorage(); } $acePropertyChanges = $propertyChanges['aces']->contains($ace)? $propertyChanges['aces']->offsetGet($ace) : array(); if (isset($acePropertyChanges[$propertyName])) { $oldValue = $acePropertyChanges[$propertyName][0]; if ($oldValue === $newValue) { unset($acePropertyChanges[$propertyName]); } else { $acePropertyChanges[$propertyName] = array($oldValue, $newValue); } } else { $acePropertyChanges[$propertyName] = array($oldValue, $newValue); } if (count($acePropertyChanges) > 0) { $propertyChanges['aces']->offsetSet($ace, $acePropertyChanges); } else { $propertyChanges['aces']->offsetUnset($ace); if (0 === count($propertyChanges['aces'])) { unset($propertyChanges['aces']); } } } $this->propertyChanges->offsetSet($sender, $propertyChanges); } /** * {@inheritDoc} */ public function updateAcl(MutableAclInterface $acl) { if (!$this->propertyChanges->contains($acl)) { throw new \InvalidArgumentException('$acl is not tracked by this provider.'); } $propertyChanges = $this->propertyChanges->offsetGet($acl); // check if any changes were made to this ACL if (0 === count($propertyChanges)) { return; } $sets = $sharedPropertyChanges = array(); $this->connection->beginTransaction(); try { if (isset($propertyChanges['entriesInheriting'])) { $sets[] = 'entries_inheriting = '.$this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['entriesInheriting'][1]); } if (isset($propertyChanges['parentAcl'])) { if (null === $propertyChanges['parentAcl'][1]) { $sets[] = 'parent_object_identity_id = NULL'; } else { $sets[] = 'parent_object_identity_id = '.intval($propertyChanges['parentAcl'][1]->getId()); } $this->regenerateAncestorRelations($acl); $childAcls = $this->findAcls($this->findChildren($acl->getObjectIdentity(), false)); foreach ($childAcls as $childOid) { $this->regenerateAncestorRelations($childAcls[$childOid]); } } // check properties for deleted, and created ACEs, and perform deletions // we need to perfom deletions before updating existing ACEs, in order to // preserve uniqueness of the order field if (isset($propertyChanges['classAces'])) { $this->updateOldAceProperty('classAces', $propertyChanges['classAces']); } if (isset($propertyChanges['classFieldAces'])) { $this->updateOldFieldAceProperty('classFieldAces', $propertyChanges['classFieldAces']); } if (isset($propertyChanges['objectAces'])) { $this->updateOldAceProperty('objectAces', $propertyChanges['objectAces']); } if (isset($propertyChanges['objectFieldAces'])) { $this->updateOldFieldAceProperty('objectFieldAces', $propertyChanges['objectFieldAces']); } // this includes only updates of existing ACEs, but neither the creation, nor // the deletion of ACEs; these are tracked by changes to the ACL's respective // properties (classAces, classFieldAces, objectAces, objectFieldAces) if (isset($propertyChanges['aces'])) { $this->updateAces($propertyChanges['aces']); } // check properties for deleted, and created ACEs, and perform creations if (isset($propertyChanges['classAces'])) { $this->updateNewAceProperty('classAces', $propertyChanges['classAces']); $sharedPropertyChanges['classAces'] = $propertyChanges['classAces']; } if (isset($propertyChanges['classFieldAces'])) { $this->updateNewFieldAceProperty('classFieldAces', $propertyChanges['classFieldAces']); $sharedPropertyChanges['classFieldAces'] = $propertyChanges['classFieldAces']; } if (isset($propertyChanges['objectAces'])) { $this->updateNewAceProperty('objectAces', $propertyChanges['objectAces']); } if (isset($propertyChanges['objectFieldAces'])) { $this->updateNewFieldAceProperty('objectFieldAces', $propertyChanges['objectFieldAces']); } // if there have been changes to shared properties, we need to synchronize other // ACL instances for object identities of the same type that are already in-memory if (count($sharedPropertyChanges) > 0) { $classAcesProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Acl', 'classAces'); $classAcesProperty->setAccessible(true); $classFieldAcesProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Acl', 'classFieldAces'); $classFieldAcesProperty->setAccessible(true); foreach ($this->loadedAcls[$acl->getObjectIdentity()->getType()] as $sameTypeAcl) { if (isset($sharedPropertyChanges['classAces'])) { if ($acl !== $sameTypeAcl && $classAcesProperty->getValue($sameTypeAcl) !== $sharedPropertyChanges['classAces'][0]) { throw new ConcurrentModificationException('The "classAces" property has been modified concurrently.'); } $classAcesProperty->setValue($sameTypeAcl, $sharedPropertyChanges['classAces'][1]); } if (isset($sharedPropertyChanges['classFieldAces'])) { if ($acl !== $sameTypeAcl && $classFieldAcesProperty->getValue($sameTypeAcl) !== $sharedPropertyChanges['classFieldAces'][0]) { throw new ConcurrentModificationException('The "classFieldAces" property has been modified concurrently.'); } $classFieldAcesProperty->setValue($sameTypeAcl, $sharedPropertyChanges['classFieldAces'][1]); } } } // persist any changes to the acl_object_identities table if (count($sets) > 0) { $this->connection->executeQuery($this->getUpdateObjectIdentitySql($acl->getId(), $sets)); } $this->connection->commit(); } catch (\Exception $failed) { $this->connection->rollBack(); throw $failed; } $this->propertyChanges->offsetSet($acl, array()); if (null !== $this->cache) { if (count($sharedPropertyChanges) > 0) { // FIXME: Currently, there is no easy way to clear the cache for ACLs // of a certain type. The problem here is that we need to make // sure to clear the cache of all child ACLs as well, and these // child ACLs might be of a different class type. $this->cache->clearCache(); } else { // if there are no shared property changes, it's sufficient to just delete // the cache for this ACL $this->cache->evictFromCacheByIdentity($acl->getObjectIdentity()); foreach ($this->findChildren($acl->getObjectIdentity()) as $childOid) { $this->cache->evictFromCacheByIdentity($childOid); } } } } /** * Constructs the SQL for deleting access control entries. * * @param integer $oidPK * @return string */ protected function getDeleteAccessControlEntriesSql($oidPK) { return sprintf( 'DELETE FROM %s WHERE object_identity_id = %d', $this->options['entry_table_name'], $oidPK ); } /** * Constructs the SQL for deleting a specific ACE. * * @param integer $acePK * @return string */ protected function getDeleteAccessControlEntrySql($acePK) { return sprintf( 'DELETE FROM %s WHERE id = %d', $this->options['entry_table_name'], $acePK ); } /** * Constructs the SQL for deleting an object identity. * * @param integer $pk * @return string */ protected function getDeleteObjectIdentitySql($pk) { return sprintf( 'DELETE FROM %s WHERE id = %d', $this->options['oid_table_name'], $pk ); } /** * Constructs the SQL for deleting relation entries. * * @param integer $pk * @return string */ protected function getDeleteObjectIdentityRelationsSql($pk) { return sprintf( 'DELETE FROM %s WHERE object_identity_id = %d', $this->options['oid_ancestors_table_name'], $pk ); } /** * Constructs the SQL for inserting an ACE. * * @param integer $classId * @param integer|null $objectIdentityId * @param string|null $field * @param integer $aceOrder * @param integer $securityIdentityId * @param string $strategy * @param integer $mask * @param Boolean $granting * @param Boolean $auditSuccess * @param Boolean $auditFailure * @return string */ protected function getInsertAccessControlEntrySql($classId, $objectIdentityId, $field, $aceOrder, $securityIdentityId, $strategy, $mask, $granting, $auditSuccess, $auditFailure) { $query = <<options['entry_table_name'], $classId, null === $objectIdentityId? 'NULL' : intval($objectIdentityId), null === $field? 'NULL' : $this->connection->quote($field), $aceOrder, $securityIdentityId, $mask, $this->connection->getDatabasePlatform()->convertBooleans($granting), $this->connection->quote($strategy), $this->connection->getDatabasePlatform()->convertBooleans($auditSuccess), $this->connection->getDatabasePlatform()->convertBooleans($auditFailure) ); } /** * Constructs the SQL for inserting a new class type. * * @param string $classType * @return string */ protected function getInsertClassSql($classType) { return sprintf( 'INSERT INTO %s (class_type) VALUES (%s)', $this->options['class_table_name'], $this->connection->quote($classType) ); } /** * Constructs the SQL for inserting a relation entry. * * @param integer $objectIdentityId * @param integer $ancestorId * @return string */ protected function getInsertObjectIdentityRelationSql($objectIdentityId, $ancestorId) { return sprintf( 'INSERT INTO %s (object_identity_id, ancestor_id) VALUES (%d, %d)', $this->options['oid_ancestors_table_name'], $objectIdentityId, $ancestorId ); } /** * Constructs the SQL for inserting an object identity. * * @param string $identifier * @param integer $classId * @param Boolean $entriesInheriting * @return string */ protected function getInsertObjectIdentitySql($identifier, $classId, $entriesInheriting) { $query = <<options['oid_table_name'], $classId, $this->connection->quote($identifier), $this->connection->getDatabasePlatform()->convertBooleans($entriesInheriting) ); } /** * Constructs the SQL for inserting a security identity. * * @param SecurityIdentityInterface $sid * @throws \InvalidArgumentException * @return string */ protected function getInsertSecurityIdentitySql(SecurityIdentityInterface $sid) { if ($sid instanceof UserSecurityIdentity) { $identifier = $sid->getClass().'-'.$sid->getUsername(); $username = true; } elseif ($sid instanceof RoleSecurityIdentity) { $identifier = $sid->getRole(); $username = false; } else { throw new \InvalidArgumentException('$sid must either be an instance of UserSecurityIdentity, or RoleSecurityIdentity.'); } return sprintf( 'INSERT INTO %s (identifier, username) VALUES (%s, %s)', $this->options['sid_table_name'], $this->connection->quote($identifier), $this->connection->getDatabasePlatform()->convertBooleans($username) ); } /** * Constructs the SQL for selecting an ACE. * * @param integer $classId * @param integer $oid * @param string $field * @param integer $order * @return string */ protected function getSelectAccessControlEntryIdSql($classId, $oid, $field, $order) { return sprintf( 'SELECT id FROM %s WHERE class_id = %d AND %s AND %s AND ace_order = %d', $this->options['entry_table_name'], $classId, null === $oid ? $this->connection->getDatabasePlatform()->getIsNullExpression('object_identity_id') : 'object_identity_id = '.intval($oid), null === $field ? $this->connection->getDatabasePlatform()->getIsNullExpression('field_name') : 'field_name = '.$this->connection->quote($field), $order ); } /** * Constructs the SQL for selecting the primary key associated with * the passed class type. * * @param string $classType * @return string */ protected function getSelectClassIdSql($classType) { return sprintf( 'SELECT id FROM %s WHERE class_type = %s', $this->options['class_table_name'], $this->connection->quote($classType) ); } /** * Constructs the SQL for selecting the primary key of a security identity. * * @param SecurityIdentityInterface $sid * @throws \InvalidArgumentException * @return string */ protected function getSelectSecurityIdentityIdSql(SecurityIdentityInterface $sid) { if ($sid instanceof UserSecurityIdentity) { $identifier = $sid->getClass().'-'.$sid->getUsername(); $username = true; } elseif ($sid instanceof RoleSecurityIdentity) { $identifier = $sid->getRole(); $username = false; } else { throw new \InvalidArgumentException('$sid must either be an instance of UserSecurityIdentity, or RoleSecurityIdentity.'); } return sprintf( 'SELECT id FROM %s WHERE identifier = %s AND username = %s', $this->options['sid_table_name'], $this->connection->quote($identifier), $this->connection->getDatabasePlatform()->convertBooleans($username) ); } /** * Constructs the SQL for updating an object identity. * * @param integer $pk * @param array $changes * @throws \InvalidArgumentException * @return string */ protected function getUpdateObjectIdentitySql($pk, array $changes) { if (0 === count($changes)) { throw new \InvalidArgumentException('There are no changes.'); } return sprintf( 'UPDATE %s SET %s WHERE id = %d', $this->options['oid_table_name'], implode(', ', $changes), $pk ); } /** * Constructs the SQL for updating an ACE. * * @param integer $pk * @param array $sets * @throws \InvalidArgumentException * @return string */ protected function getUpdateAccessControlEntrySql($pk, array $sets) { if (0 === count($sets)) { throw new \InvalidArgumentException('There are no changes.'); } return sprintf( 'UPDATE %s SET %s WHERE id = %d', $this->options['entry_table_name'], implode(', ', $sets), $pk ); } /** * Creates the ACL for the passed object identity * * @param ObjectIdentityInterface $oid */ private function createObjectIdentity(ObjectIdentityInterface $oid) { $classId = $this->createOrRetrieveClassId($oid->getType()); $this->connection->executeQuery($this->getInsertObjectIdentitySql($oid->getIdentifier(), $classId, true)); } /** * Returns the primary key for the passed class type. * * If the type does not yet exist in the database, it will be created. * * @param string $classType * @return integer */ private function createOrRetrieveClassId($classType) { if (false !== $id = $this->connection->executeQuery($this->getSelectClassIdSql($classType))->fetchColumn()) { return $id; } $this->connection->executeQuery($this->getInsertClassSql($classType)); return $this->connection->executeQuery($this->getSelectClassIdSql($classType))->fetchColumn(); } /** * Returns the primary key for the passed security identity. * * If the security identity does not yet exist in the database, it will be * created. * * @param SecurityIdentityInterface $sid * @return integer */ private function createOrRetrieveSecurityIdentityId(SecurityIdentityInterface $sid) { if (false !== $id = $this->connection->executeQuery($this->getSelectSecurityIdentityIdSql($sid))->fetchColumn()) { return $id; } $this->connection->executeQuery($this->getInsertSecurityIdentitySql($sid)); return $this->connection->executeQuery($this->getSelectSecurityIdentityIdSql($sid))->fetchColumn(); } /** * Deletes all ACEs for the given object identity primary key. * * @param integer $oidPK */ private function deleteAccessControlEntries($oidPK) { $this->connection->executeQuery($this->getDeleteAccessControlEntriesSql($oidPK)); } /** * Deletes the object identity from the database. * * @param integer $pk */ private function deleteObjectIdentity($pk) { $this->connection->executeQuery($this->getDeleteObjectIdentitySql($pk)); } /** * Deletes all entries from the relations table from the database. * * @param integer $pk */ private function deleteObjectIdentityRelations($pk) { $this->connection->executeQuery($this->getDeleteObjectIdentityRelationsSql($pk)); } /** * This regenerates the ancestor table which is used for fast read access. * * @param AclInterface $acl */ private function regenerateAncestorRelations(AclInterface $acl) { $pk = $acl->getId(); $this->connection->executeQuery($this->getDeleteObjectIdentityRelationsSql($pk)); $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $pk)); $parentAcl = $acl->getParentAcl(); while (null !== $parentAcl) { $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $parentAcl->getId())); $parentAcl = $parentAcl->getParentAcl(); } } /** * This processes new entries changes on an ACE related property (classFieldAces, or objectFieldAces). * * @param string $name * @param array $changes */ private function updateNewFieldAceProperty($name, array $changes) { $sids = new \SplObjectStorage(); $classIds = new \SplObjectStorage(); $currentIds = array(); foreach ($changes[1] as $field => $new) { for ($i=0,$c=count($new); $i<$c; $i++) { $ace = $new[$i]; if (null === $ace->getId()) { if ($sids->contains($ace->getSecurityIdentity())) { $sid = $sids->offsetGet($ace->getSecurityIdentity()); } else { $sid = $this->createOrRetrieveSecurityIdentityId($ace->getSecurityIdentity()); } $oid = $ace->getAcl()->getObjectIdentity(); if ($classIds->contains($oid)) { $classId = $classIds->offsetGet($oid); } else { $classId = $this->createOrRetrieveClassId($oid->getType()); } $objectIdentityId = $name === 'classFieldAces' ? null : $ace->getAcl()->getId(); $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, $field, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure())); $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, $field, $i))->fetchColumn(); $this->loadedAces[$aceId] = $ace; $aceIdProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Entry', 'id'); $aceIdProperty->setAccessible(true); $aceIdProperty->setValue($ace, intval($aceId)); } else { $currentIds[$ace->getId()] = true; } } } } /** * This process old entries changes on an ACE related property (classFieldAces, or objectFieldAces). * * @param string $name * @param array $changes */ private function updateOldFieldAceProperty($ane, array $changes) { $currentIds = array(); foreach ($changes[1] as $field => $new) { for ($i = 0, $c = count($new); $i < $c; $i++) { $ace = $new[$i]; if (null !== $ace->getId()) { $currentIds[$ace->getId()] = true; } } } foreach ($changes[0] as $old) { for ($i = 0, $c = count($old); $i < $c; $i++) { $ace = $old[$i]; if (!isset($currentIds[$ace->getId()])) { $this->connection->executeQuery($this->getDeleteAccessControlEntrySql($ace->getId())); unset($this->loadedAces[$ace->getId()]); } } } } /** * This processes new entries changes on an ACE related property (classAces, or objectAces). * * @param string $name * @param array $changes */ private function updateNewAceProperty($name, array $changes) { list($old, $new) = $changes; $sids = new \SplObjectStorage(); $classIds = new \SplObjectStorage(); $currentIds = array(); for ($i=0,$c=count($new); $i<$c; $i++) { $ace = $new[$i]; if (null === $ace->getId()) { if ($sids->contains($ace->getSecurityIdentity())) { $sid = $sids->offsetGet($ace->getSecurityIdentity()); } else { $sid = $this->createOrRetrieveSecurityIdentityId($ace->getSecurityIdentity()); } $oid = $ace->getAcl()->getObjectIdentity(); if ($classIds->contains($oid)) { $classId = $classIds->offsetGet($oid); } else { $classId = $this->createOrRetrieveClassId($oid->getType()); } $objectIdentityId = $name === 'classAces' ? null : $ace->getAcl()->getId(); $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, null, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure())); $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, null, $i))->fetchColumn(); $this->loadedAces[$aceId] = $ace; $aceIdProperty = new \ReflectionProperty($ace, 'id'); $aceIdProperty->setAccessible(true); $aceIdProperty->setValue($ace, intval($aceId)); } else { $currentIds[$ace->getId()] = true; } } } /** * This processes old entries changes on an ACE related property (classAces, or objectAces). * * @param string $name * @param array $changes */ private function updateOldAceProperty($name, array $changes) { list($old, $new) = $changes; $currentIds = array(); for ($i=0,$c=count($new); $i<$c; $i++) { $ace = $new[$i]; if (null !== $ace->getId()) { $currentIds[$ace->getId()] = true; } } for ($i = 0, $c = count($old); $i < $c; $i++) { $ace = $old[$i]; if (!isset($currentIds[$ace->getId()])) { $this->connection->executeQuery($this->getDeleteAccessControlEntrySql($ace->getId())); unset($this->loadedAces[$ace->getId()]); } } } /** * Persists the changes which were made to ACEs to the database. * * @param \SplObjectStorage $aces */ private function updateAces(\SplObjectStorage $aces) { foreach ($aces as $ace) { $this->updateAce($aces, $ace); } } private function updateAce(\SplObjectStorage $aces, $ace) { $propertyChanges = $aces->offsetGet($ace); $sets = array(); if (isset($propertyChanges['aceOrder']) && $propertyChanges['aceOrder'][1] > $propertyChanges['aceOrder'][0] && $propertyChanges == $aces->offsetGet($ace)) { $aces->next(); if ($aces->valid()) { $this->updateAce($aces, $aces->current()); } } if (isset($propertyChanges['mask'])) { $sets[] = sprintf('mask = %d', $propertyChanges['mask'][1]); } if (isset($propertyChanges['strategy'])) { $sets[] = sprintf('granting_strategy = %s', $this->connection->quote($propertyChanges['strategy'])); } if (isset($propertyChanges['aceOrder'])) { $sets[] = sprintf('ace_order = %d', $propertyChanges['aceOrder'][1]); } if (isset($propertyChanges['auditSuccess'])) { $sets[] = sprintf('audit_success = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditSuccess'][1])); } if (isset($propertyChanges['auditFailure'])) { $sets[] = sprintf('audit_failure = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditFailure'][1])); } $this->connection->executeQuery($this->getUpdateAccessControlEntrySql($ace->getId(), $sets)); } } PK] 9Security/Acl/Domain/SecurityIdentityRetrievalStrategy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter; /** * Strategy for retrieving security identities * * @author Johannes M. Schmitt */ class SecurityIdentityRetrievalStrategy implements SecurityIdentityRetrievalStrategyInterface { private $roleHierarchy; private $authenticationTrustResolver; /** * Constructor * * @param RoleHierarchyInterface $roleHierarchy * @param AuthenticationTrustResolver $authenticationTrustResolver */ public function __construct(RoleHierarchyInterface $roleHierarchy, AuthenticationTrustResolver $authenticationTrustResolver) { $this->roleHierarchy = $roleHierarchy; $this->authenticationTrustResolver = $authenticationTrustResolver; } /** * {@inheritDoc} */ public function getSecurityIdentities(TokenInterface $token) { $sids = array(); // add user security identity if (!$token instanceof AnonymousToken) { try { $sids[] = UserSecurityIdentity::fromToken($token); } catch (\InvalidArgumentException $invalid) { // ignore, user has no user security identity } } // add all reachable roles foreach ($this->roleHierarchy->getReachableRoles($token->getRoles()) as $role) { $sids[] = new RoleSecurityIdentity($role); } // add built-in special roles if ($this->authenticationTrustResolver->isFullFledged($token)) { $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_FULLY); $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_REMEMBERED); $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY); } elseif ($this->authenticationTrustResolver->isRememberMe($token)) { $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_REMEMBERED); $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY); } elseif ($this->authenticationTrustResolver->isAnonymous($token)) { $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY); } return $sids; } } PK](]2Security/Acl/Domain/PermissionGrantingStrategy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Exception\NoAceFoundException; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\AuditLoggerInterface; use Symfony\Component\Security\Acl\Model\EntryInterface; use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * The permission granting strategy to apply to the access control list. * * @author Johannes M. Schmitt */ class PermissionGrantingStrategy implements PermissionGrantingStrategyInterface { const EQUAL = 'equal'; const ALL = 'all'; const ANY = 'any'; private $auditLogger; /** * Sets the audit logger * * @param AuditLoggerInterface $auditLogger */ public function setAuditLogger(AuditLoggerInterface $auditLogger) { $this->auditLogger = $auditLogger; } /** * {@inheritDoc} */ public function isGranted(AclInterface $acl, array $masks, array $sids, $administrativeMode = false) { try { try { $aces = $acl->getObjectAces(); if (!$aces) { throw new NoAceFoundException(); } return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode); } catch (NoAceFoundException $noObjectAce) { $aces = $acl->getClassAces(); if (!$aces) { throw $noObjectAce; } return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode); } } catch (NoAceFoundException $noClassAce) { if ($acl->isEntriesInheriting() && null !== $parentAcl = $acl->getParentAcl()) { return $parentAcl->isGranted($masks, $sids, $administrativeMode); } throw $noClassAce; } } /** * {@inheritDoc} */ public function isFieldGranted(AclInterface $acl, $field, array $masks, array $sids, $administrativeMode = false) { try { try { $aces = $acl->getObjectFieldAces($field); if (!$aces) { throw new NoAceFoundException(); } return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode); } catch (NoAceFoundException $noObjectAces) { $aces = $acl->getClassFieldAces($field); if (!$aces) { throw $noObjectAces; } return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode); } } catch (NoAceFoundException $noClassAces) { if ($acl->isEntriesInheriting() && null !== $parentAcl = $acl->getParentAcl()) { return $parentAcl->isFieldGranted($field, $masks, $sids, $administrativeMode); } throw $noClassAces; } } /** * Makes an authorization decision. * * The order of ACEs, and SIDs is significant; the order of permission masks * not so much. It is important to note that the more specific security * identities should be at the beginning of the SIDs array in order for this * strategy to produce intuitive authorization decisions. * * First, we will iterate over permissions, then over security identities. * For each combination of permission, and identity we will test the * available ACEs until we find one which is applicable. * * The first applicable ACE will make the ultimate decision for the * permission/identity combination. If it is granting, this method will return * true, if it is denying, the method will continue to check the next * permission/identity combination. * * This process is repeated until either a granting ACE is found, or no * permission/identity combinations are left. Finally, we will either throw * an NoAceFoundException, or deny access. * * @param AclInterface $acl * @param EntryInterface[] $aces An array of ACE to check against * @param array $masks An array of permission masks * @param SecurityIdentityInterface[] $sids An array of SecurityIdentityInterface implementations * @param Boolean $administrativeMode True turns off audit logging * * @return Boolean true, or false; either granting, or denying access respectively. * * @throws NoAceFoundException */ private function hasSufficientPermissions(AclInterface $acl, array $aces, array $masks, array $sids, $administrativeMode) { $firstRejectedAce = null; foreach ($masks as $requiredMask) { foreach ($sids as $sid) { foreach ($aces as $ace) { if ($sid->equals($ace->getSecurityIdentity()) && $this->isAceApplicable($requiredMask, $ace)) { if ($ace->isGranting()) { if (!$administrativeMode && null !== $this->auditLogger) { $this->auditLogger->logIfNeeded(true, $ace); } return true; } if (null === $firstRejectedAce) { $firstRejectedAce = $ace; } break 2; } } } } if (null !== $firstRejectedAce) { if (!$administrativeMode && null !== $this->auditLogger) { $this->auditLogger->logIfNeeded(false, $firstRejectedAce); } return false; } throw new NoAceFoundException(); } /** * Determines whether the ACE is applicable to the given permission/security * identity combination. * * Per default, we support three different comparison strategies. * * Strategy ALL: * The ACE will be considered applicable when all the turned-on bits in the * required mask are also turned-on in the ACE mask. * * Strategy ANY: * The ACE will be considered applicable when any of the turned-on bits in * the required mask is also turned-on the in the ACE mask. * * Strategy EQUAL: * The ACE will be considered applicable when the bitmasks are equal. * * @param integer $requiredMask * @param EntryInterface $ace * * @return Boolean * * @throws \RuntimeException if the ACE strategy is not supported */ private function isAceApplicable($requiredMask, EntryInterface $ace) { $strategy = $ace->getStrategy(); if (self::ALL === $strategy) { return $requiredMask === ($ace->getMask() & $requiredMask); } elseif (self::ANY === $strategy) { return 0 !== ($ace->getMask() & $requiredMask); } elseif (self::EQUAL === $strategy) { return $requiredMask === $ace->getMask(); } throw new \RuntimeException(sprintf('The strategy "%s" is not supported.', $strategy)); } } PK]X / / *Security/Acl/Domain/AclCollectionCache.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Model\AclProviderInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * This service caches ACLs for an entire collection of objects. * * @author Johannes M. Schmitt */ class AclCollectionCache { private $aclProvider; private $objectIdentityRetrievalStrategy; private $securityIdentityRetrievalStrategy; /** * Constructor. * * @param AclProviderInterface $aclProvider * @param ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy * @param SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy */ public function __construct(AclProviderInterface $aclProvider, ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy, SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy) { $this->aclProvider = $aclProvider; $this->objectIdentityRetrievalStrategy = $oidRetrievalStrategy; $this->securityIdentityRetrievalStrategy = $sidRetrievalStrategy; } /** * Batch loads ACLs for an entire collection; thus, it reduces the number * of required queries considerably. * * @param mixed $collection anything that can be passed to foreach() * @param TokenInterface[] $tokens an array of TokenInterface implementations */ public function cache($collection, array $tokens = array()) { $sids = array(); foreach ($tokens as $token) { $sids = array_merge($sids, $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token)); } $oids = array(); foreach ($collection as $domainObject) { $oids[] = $this->objectIdentityRetrievalStrategy->getObjectIdentity($domainObject); } $this->aclProvider->findAcls($oids, $sids); } } PK]%}`M`MSecurity/Acl/Domain/Acl.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Doctrine\Common\NotifyPropertyChanged; use Doctrine\Common\PropertyChangedListener; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\AuditableAclInterface; use Symfony\Component\Security\Acl\Model\EntryInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * An ACL implementation. * * Each object identity has exactly one associated ACL. Each ACL can have four * different types of ACEs (class ACEs, object ACEs, class field ACEs, object field * ACEs). * * You should not iterate over the ACEs yourself, but instead use isGranted(), * or isFieldGranted(). These will utilize an implementation of PermissionGrantingStrategy * internally. * * @author Johannes M. Schmitt */ class Acl implements AuditableAclInterface, NotifyPropertyChanged { private $parentAcl; private $permissionGrantingStrategy; private $objectIdentity; private $classAces = array(); private $classFieldAces = array(); private $objectAces = array(); private $objectFieldAces = array(); private $id; private $loadedSids; private $entriesInheriting; private $listeners = array(); /** * Constructor * * @param integer $id * @param ObjectIdentityInterface $objectIdentity * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy * @param array $loadedSids * @param Boolean $entriesInheriting */ public function __construct($id, ObjectIdentityInterface $objectIdentity, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $loadedSids = array(), $entriesInheriting) { $this->id = $id; $this->objectIdentity = $objectIdentity; $this->permissionGrantingStrategy = $permissionGrantingStrategy; $this->loadedSids = $loadedSids; $this->entriesInheriting = $entriesInheriting; } /** * Adds a property changed listener * * @param PropertyChangedListener $listener */ public function addPropertyChangedListener(PropertyChangedListener $listener) { $this->listeners[] = $listener; } /** * {@inheritDoc} */ public function deleteClassAce($index) { $this->deleteAce('classAces', $index); } /** * {@inheritDoc} */ public function deleteClassFieldAce($index, $field) { $this->deleteFieldAce('classFieldAces', $index, $field); } /** * {@inheritDoc} */ public function deleteObjectAce($index) { $this->deleteAce('objectAces', $index); } /** * {@inheritDoc} */ public function deleteObjectFieldAce($index, $field) { $this->deleteFieldAce('objectFieldAces', $index, $field); } /** * {@inheritDoc} */ public function getClassAces() { return $this->classAces; } /** * {@inheritDoc} */ public function getClassFieldAces($field) { return isset($this->classFieldAces[$field])? $this->classFieldAces[$field] : array(); } /** * {@inheritDoc} */ public function getObjectAces() { return $this->objectAces; } /** * {@inheritDoc} */ public function getObjectFieldAces($field) { return isset($this->objectFieldAces[$field]) ? $this->objectFieldAces[$field] : array(); } /** * {@inheritDoc} */ public function getId() { return $this->id; } /** * {@inheritDoc} */ public function getObjectIdentity() { return $this->objectIdentity; } /** * {@inheritDoc} */ public function getParentAcl() { return $this->parentAcl; } /** * {@inheritDoc} */ public function insertClassAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null) { $this->insertAce('classAces', $index, $mask, $sid, $granting, $strategy); } /** * {@inheritDoc} */ public function insertClassFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null) { $this->insertFieldAce('classFieldAces', $index, $field, $mask, $sid, $granting, $strategy); } /** * {@inheritDoc} */ public function insertObjectAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null) { $this->insertAce('objectAces', $index, $mask, $sid, $granting, $strategy); } /** * {@inheritDoc} */ public function insertObjectFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null) { $this->insertFieldAce('objectFieldAces', $index, $field, $mask, $sid, $granting, $strategy); } /** * {@inheritDoc} */ public function isEntriesInheriting() { return $this->entriesInheriting; } /** * {@inheritDoc} */ public function isFieldGranted($field, array $masks, array $securityIdentities, $administrativeMode = false) { return $this->permissionGrantingStrategy->isFieldGranted($this, $field, $masks, $securityIdentities, $administrativeMode); } /** * {@inheritDoc} */ public function isGranted(array $masks, array $securityIdentities, $administrativeMode = false) { return $this->permissionGrantingStrategy->isGranted($this, $masks, $securityIdentities, $administrativeMode); } /** * {@inheritDoc} */ public function isSidLoaded($sids) { if (!$this->loadedSids) { return true; } if (!is_array($sids)) { $sids = array($sids); } foreach ($sids as $sid) { if (!$sid instanceof SecurityIdentityInterface) { throw new \InvalidArgumentException( '$sid must be an instance of SecurityIdentityInterface.'); } foreach ($this->loadedSids as $loadedSid) { if ($loadedSid->equals($sid)) { continue 2; } } return false; } return true; } /** * Implementation for the \Serializable interface * * @return string */ public function serialize() { return serialize(array( null === $this->parentAcl ? null : $this->parentAcl->getId(), $this->objectIdentity, $this->classAces, $this->classFieldAces, $this->objectAces, $this->objectFieldAces, $this->id, $this->loadedSids, $this->entriesInheriting, )); } /** * Implementation for the \Serializable interface * * @param string $serialized */ public function unserialize($serialized) { list($this->parentAcl, $this->objectIdentity, $this->classAces, $this->classFieldAces, $this->objectAces, $this->objectFieldAces, $this->id, $this->loadedSids, $this->entriesInheriting ) = unserialize($serialized); $this->listeners = array(); } /** * {@inheritDoc} */ public function setEntriesInheriting($boolean) { if ($this->entriesInheriting !== $boolean) { $this->onPropertyChanged('entriesInheriting', $this->entriesInheriting, $boolean); $this->entriesInheriting = $boolean; } } /** * {@inheritDoc} */ public function setParentAcl(AclInterface $acl = null) { if (null !== $acl && null === $acl->getId()) { throw new \InvalidArgumentException('$acl must have an ID.'); } if ($this->parentAcl !== $acl) { $this->onPropertyChanged('parentAcl', $this->parentAcl, $acl); $this->parentAcl = $acl; } } /** * {@inheritDoc} */ public function updateClassAce($index, $mask, $strategy = null) { $this->updateAce('classAces', $index, $mask, $strategy); } /** * {@inheritDoc} */ public function updateClassFieldAce($index, $field, $mask, $strategy = null) { $this->updateFieldAce('classFieldAces', $index, $field, $mask, $strategy); } /** * {@inheritDoc} */ public function updateObjectAce($index, $mask, $strategy = null) { $this->updateAce('objectAces', $index, $mask, $strategy); } /** * {@inheritDoc} */ public function updateObjectFieldAce($index, $field, $mask, $strategy = null) { $this->updateFieldAce('objectFieldAces', $index, $field, $mask, $strategy); } /** * {@inheritDoc} */ public function updateClassAuditing($index, $auditSuccess, $auditFailure) { $this->updateAuditing($this->classAces, $index, $auditSuccess, $auditFailure); } /** * {@inheritDoc} */ public function updateClassFieldAuditing($index, $field, $auditSuccess, $auditFailure) { if (!isset($this->classFieldAces[$field])) { throw new \InvalidArgumentException(sprintf('There are no ACEs for field "%s".', $field)); } $this->updateAuditing($this->classFieldAces[$field], $index, $auditSuccess, $auditFailure); } /** * {@inheritDoc} */ public function updateObjectAuditing($index, $auditSuccess, $auditFailure) { $this->updateAuditing($this->objectAces, $index, $auditSuccess, $auditFailure); } /** * {@inheritDoc} */ public function updateObjectFieldAuditing($index, $field, $auditSuccess, $auditFailure) { if (!isset($this->objectFieldAces[$field])) { throw new \InvalidArgumentException(sprintf('There are no ACEs for field "%s".', $field)); } $this->updateAuditing($this->objectFieldAces[$field], $index, $auditSuccess, $auditFailure); } /** * Deletes an ACE * * @param string $property * @param integer $index * @throws \OutOfBoundsException */ private function deleteAce($property, $index) { $aces =& $this->$property; if (!isset($aces[$index])) { throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index)); } $oldValue = $this->$property; unset($aces[$index]); $this->$property = array_values($this->$property); $this->onPropertyChanged($property, $oldValue, $this->$property); for ($i=$index,$c=count($this->$property); $i<$c; $i++) { $this->onEntryPropertyChanged($aces[$i], 'aceOrder', $i+1, $i); } } /** * Deletes a field-based ACE * * @param string $property * @param integer $index * @param string $field * @throws \OutOfBoundsException */ private function deleteFieldAce($property, $index, $field) { $aces =& $this->$property; if (!isset($aces[$field][$index])) { throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index)); } $oldValue = $this->$property; unset($aces[$field][$index]); $aces[$field] = array_values($aces[$field]); $this->onPropertyChanged($property, $oldValue, $this->$property); for ($i=$index,$c=count($aces[$field]); $i<$c; $i++) { $this->onEntryPropertyChanged($aces[$field][$i], 'aceOrder', $i+1, $i); } } /** * Inserts an ACE * * @param string $property * @param integer $index * @param integer $mask * @param SecurityIdentityInterface $sid * @param Boolean $granting * @param string $strategy * @throws \OutOfBoundsException * @throws \InvalidArgumentException */ private function insertAce($property, $index, $mask, SecurityIdentityInterface $sid, $granting, $strategy = null) { if ($index < 0 || $index > count($this->$property)) { throw new \OutOfBoundsException(sprintf('The index must be in the interval [0, %d].', count($this->$property))); } if (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } if (null === $strategy) { if (true === $granting) { $strategy = PermissionGrantingStrategy::ALL; } else { $strategy = PermissionGrantingStrategy::ANY; } } $aces =& $this->$property; $oldValue = $this->$property; if (isset($aces[$index])) { $this->$property = array_merge( array_slice($this->$property, 0, $index), array(true), array_slice($this->$property, $index) ); for ($i=$index,$c=count($this->$property)-1; $i<$c; $i++) { $this->onEntryPropertyChanged($aces[$i+1], 'aceOrder', $i, $i+1); } } $aces[$index] = new Entry(null, $this, $sid, $strategy, $mask, $granting, false, false); $this->onPropertyChanged($property, $oldValue, $this->$property); } /** * Inserts a field-based ACE * * @param string $property * @param integer $index * @param string $field * @param integer $mask * @param SecurityIdentityInterface $sid * @param Boolean $granting * @param string $strategy * @throws \InvalidArgumentException * @throws \OutOfBoundsException */ private function insertFieldAce($property, $index, $field, $mask, SecurityIdentityInterface $sid, $granting, $strategy = null) { if (0 === strlen($field)) { throw new \InvalidArgumentException('$field cannot be empty.'); } if (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } if (null === $strategy) { if (true === $granting) { $strategy = PermissionGrantingStrategy::ALL; } else { $strategy = PermissionGrantingStrategy::ANY; } } $aces =& $this->$property; if (!isset($aces[$field])) { $aces[$field] = array(); } if ($index < 0 || $index > count($aces[$field])) { throw new \OutOfBoundsException(sprintf('The index must be in the interval [0, %d].', count($this->$property))); } $oldValue = $aces; if (isset($aces[$field][$index])) { $aces[$field] = array_merge( array_slice($aces[$field], 0, $index), array(true), array_slice($aces[$field], $index) ); for ($i=$index,$c=count($aces[$field])-1; $i<$c; $i++) { $this->onEntryPropertyChanged($aces[$field][$i+1], 'aceOrder', $i, $i+1); } } $aces[$field][$index] = new FieldEntry(null, $this, $field, $sid, $strategy, $mask, $granting, false, false); $this->onPropertyChanged($property, $oldValue, $this->$property); } /** * Updates an ACE * * @param string $property * @param integer $index * @param integer $mask * @param string $strategy * @throws \OutOfBoundsException */ private function updateAce($property, $index, $mask, $strategy = null) { $aces =& $this->$property; if (!isset($aces[$index])) { throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index)); } $ace = $aces[$index]; if ($mask !== $oldMask = $ace->getMask()) { $this->onEntryPropertyChanged($ace, 'mask', $oldMask, $mask); $ace->setMask($mask); } if (null !== $strategy && $strategy !== $oldStrategy = $ace->getStrategy()) { $this->onEntryPropertyChanged($ace, 'strategy', $oldStrategy, $strategy); $ace->setStrategy($strategy); } } /** * Updates auditing for an ACE * * @param array &$aces * @param integer $index * @param Boolean $auditSuccess * @param Boolean $auditFailure * @throws \OutOfBoundsException */ private function updateAuditing(array &$aces, $index, $auditSuccess, $auditFailure) { if (!isset($aces[$index])) { throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index)); } if ($auditSuccess !== $aces[$index]->isAuditSuccess()) { $this->onEntryPropertyChanged($aces[$index], 'auditSuccess', !$auditSuccess, $auditSuccess); $aces[$index]->setAuditSuccess($auditSuccess); } if ($auditFailure !== $aces[$index]->isAuditFailure()) { $this->onEntryPropertyChanged($aces[$index], 'auditFailure', !$auditFailure, $auditFailure); $aces[$index]->setAuditFailure($auditFailure); } } /** * Updates a field-based ACE * * @param string $property * @param integer $index * @param string $field * @param integer $mask * @param string $strategy * @throws \InvalidArgumentException * @throws \OutOfBoundsException */ private function updateFieldAce($property, $index, $field, $mask, $strategy = null) { if (0 === strlen($field)) { throw new \InvalidArgumentException('$field cannot be empty.'); } $aces =& $this->$property; if (!isset($aces[$field][$index])) { throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index)); } $ace = $aces[$field][$index]; if ($mask !== $oldMask = $ace->getMask()) { $this->onEntryPropertyChanged($ace, 'mask', $oldMask, $mask); $ace->setMask($mask); } if (null !== $strategy && $strategy !== $oldStrategy = $ace->getStrategy()) { $this->onEntryPropertyChanged($ace, 'strategy', $oldStrategy, $strategy); $ace->setStrategy($strategy); } } /** * Called when a property of the ACL changes * * @param string $name * @param mixed $oldValue * @param mixed $newValue */ private function onPropertyChanged($name, $oldValue, $newValue) { foreach ($this->listeners as $listener) { $listener->propertyChanged($this, $name, $oldValue, $newValue); } } /** * Called when a property of an ACE associated with this ACL changes * * @param EntryInterface $entry * @param string $name * @param mixed $oldValue * @param mixed $newValue */ private function onEntryPropertyChanged(EntryInterface $entry, $name, $oldValue, $newValue) { foreach ($this->listeners as $listener) { $listener->propertyChanged($entry, $name, $oldValue, $newValue); } } } PK]pU"Security/Acl/Domain/FieldEntry.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\FieldEntryInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * Field-aware ACE implementation which is auditable * * @author Johannes M. Schmitt */ class FieldEntry extends Entry implements FieldEntryInterface { private $field; /** * Constructor * * @param integer $id * @param AclInterface $acl * @param string $field * @param SecurityIdentityInterface $sid * @param string $strategy * @param integer $mask * @param Boolean $granting * @param Boolean $auditFailure * @param Boolean $auditSuccess */ public function __construct($id, AclInterface $acl, $field, SecurityIdentityInterface $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess) { parent::__construct($id, $acl, $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess); $this->field = $field; } /** * {@inheritDoc} */ public function getField() { return $this->field; } /** * {@inheritDoc} */ public function serialize() { return serialize(array( $this->field, parent::serialize(), )); } /** * {@inheritDoc} */ public function unserialize($serialized) { list($this->field, $parentStr) = unserialize($serialized); parent::unserialize($parentStr); } } PK]5D[Security/Acl/Domain/Entry.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\AuditableEntryInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * Auditable ACE implementation * * @author Johannes M. Schmitt */ class Entry implements AuditableEntryInterface { private $acl; private $mask; private $id; private $securityIdentity; private $strategy; private $auditFailure; private $auditSuccess; private $granting; /** * Constructor * * @param integer $id * @param AclInterface $acl * @param SecurityIdentityInterface $sid * @param string $strategy * @param integer $mask * @param Boolean $granting * @param Boolean $auditFailure * @param Boolean $auditSuccess */ public function __construct($id, AclInterface $acl, SecurityIdentityInterface $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess) { $this->id = $id; $this->acl = $acl; $this->securityIdentity = $sid; $this->strategy = $strategy; $this->mask = $mask; $this->granting = $granting; $this->auditFailure = $auditFailure; $this->auditSuccess = $auditSuccess; } /** * {@inheritDoc} */ public function getAcl() { return $this->acl; } /** * {@inheritDoc} */ public function getMask() { return $this->mask; } /** * {@inheritDoc} */ public function getId() { return $this->id; } /** * {@inheritDoc} */ public function getSecurityIdentity() { return $this->securityIdentity; } /** * {@inheritDoc} */ public function getStrategy() { return $this->strategy; } /** * {@inheritDoc} */ public function isAuditFailure() { return $this->auditFailure; } /** * {@inheritDoc} */ public function isAuditSuccess() { return $this->auditSuccess; } /** * {@inheritDoc} */ public function isGranting() { return $this->granting; } /** * Turns on/off auditing on permissions denials. * * Do never call this method directly. Use the respective methods on the * AclInterface instead. * * @param Boolean $boolean */ public function setAuditFailure($boolean) { $this->auditFailure = $boolean; } /** * Turns on/off auditing on permission grants. * * Do never call this method directly. Use the respective methods on the * AclInterface instead. * * @param Boolean $boolean */ public function setAuditSuccess($boolean) { $this->auditSuccess = $boolean; } /** * Sets the permission mask * * Do never call this method directly. Use the respective methods on the * AclInterface instead. * * @param integer $mask */ public function setMask($mask) { $this->mask = $mask; } /** * Sets the mask comparison strategy * * Do never call this method directly. Use the respective methods on the * AclInterface instead. * * @param string $strategy */ public function setStrategy($strategy) { $this->strategy = $strategy; } /** * Implementation of \Serializable * * @return string */ public function serialize() { return serialize(array( $this->mask, $this->id, $this->securityIdentity, $this->strategy, $this->auditFailure, $this->auditSuccess, $this->granting, )); } /** * Implementation of \Serializable * * @param string $serialized */ public function unserialize($serialized) { list($this->mask, $this->id, $this->securityIdentity, $this->strategy, $this->auditFailure, $this->auditSuccess, $this->granting ) = unserialize($serialized); } } PK].* * ,Security/Acl/Domain/UserSecurityIdentity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Util\ClassUtils; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * A SecurityIdentity implementation used for actual users * * @author Johannes M. Schmitt */ final class UserSecurityIdentity implements SecurityIdentityInterface { private $username; private $class; /** * Constructor * * @param string $username the username representation * @param string $class the user's fully qualified class name * * @throws \InvalidArgumentException */ public function __construct($username, $class) { if (empty($username)) { throw new \InvalidArgumentException('$username must not be empty.'); } if (empty($class)) { throw new \InvalidArgumentException('$class must not be empty.'); } $this->username = (string) $username; $this->class = $class; } /** * Creates a user security identity from a UserInterface * * @param UserInterface $user * @return UserSecurityIdentity */ public static function fromAccount(UserInterface $user) { return new self($user->getUsername(), ClassUtils::getRealClass($user)); } /** * Creates a user security identity from a TokenInterface * * @param TokenInterface $token * @return UserSecurityIdentity */ public static function fromToken(TokenInterface $token) { $user = $token->getUser(); if ($user instanceof UserInterface) { return self::fromAccount($user); } return new self((string) $user, is_object($user) ? ClassUtils::getRealClass($user) : ClassUtils::getRealClass($token)); } /** * Returns the username * * @return string */ public function getUsername() { return $this->username; } /** * Returns the user's class name * * @return string */ public function getClass() { return $this->class; } /** * {@inheritDoc} */ public function equals(SecurityIdentityInterface $sid) { if (!$sid instanceof UserSecurityIdentity) { return false; } return $this->username === $sid->getUsername() && $this->class === $sid->getClass(); } /** * A textual representation of this security identity. * * This is not used for equality comparison, but only for debugging. * * @return string */ public function __toString() { return sprintf('UserSecurityIdentity(%s, %s)', $this->username, $this->class); } } PK]tA)==,Security/Acl/Domain/RoleSecurityIdentity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; use Symfony\Component\Security\Core\Role\Role; /** * A SecurityIdentity implementation for roles * * @author Johannes M. Schmitt */ final class RoleSecurityIdentity implements SecurityIdentityInterface { private $role; /** * Constructor * * @param mixed $role a Role instance, or its string representation */ public function __construct($role) { if ($role instanceof Role) { $role = $role->getRole(); } $this->role = $role; } /** * Returns the role name * * @return string */ public function getRole() { return $this->role; } /** * {@inheritDoc} */ public function equals(SecurityIdentityInterface $sid) { if (!$sid instanceof RoleSecurityIdentity) { return false; } return $this->role === $sid->getRole(); } /** * Returns a textual representation of this security identity. * * This is solely used for debugging purposes, not to make an equality decision. * * @return string */ public function __toString() { return sprintf('RoleSecurityIdentity(%s)', $this->role); } } PK]^@.Y Y &Security/Acl/Domain/ObjectIdentity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Core\Util\ClassUtils; use Symfony\Component\Security\Acl\Exception\InvalidDomainObjectException; use Symfony\Component\Security\Acl\Model\DomainObjectInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; /** * ObjectIdentity implementation * * @author Johannes M. Schmitt */ final class ObjectIdentity implements ObjectIdentityInterface { private $identifier; private $type; /** * Constructor. * * @param string $identifier * @param string $type * * @throws \InvalidArgumentException */ public function __construct($identifier, $type) { if (empty($identifier)) { throw new \InvalidArgumentException('$identifier cannot be empty.'); } if (empty($type)) { throw new \InvalidArgumentException('$type cannot be empty.'); } $this->identifier = $identifier; $this->type = $type; } /** * Constructs an ObjectIdentity for the given domain object * * @param object $domainObject * @throws InvalidDomainObjectException * @return ObjectIdentity */ public static function fromDomainObject($domainObject) { if (!is_object($domainObject)) { throw new InvalidDomainObjectException('$domainObject must be an object.'); } try { if ($domainObject instanceof DomainObjectInterface) { return new self($domainObject->getObjectIdentifier(), ClassUtils::getRealClass($domainObject)); } elseif (method_exists($domainObject, 'getId')) { return new self($domainObject->getId(), ClassUtils::getRealClass($domainObject)); } } catch (\InvalidArgumentException $invalid) { throw new InvalidDomainObjectException($invalid->getMessage(), 0, $invalid); } throw new InvalidDomainObjectException('$domainObject must either implement the DomainObjectInterface, or have a method named "getId".'); } /** * {@inheritDoc} */ public function getIdentifier() { return $this->identifier; } /** * {@inheritDoc} */ public function getType() { return $this->type; } /** * {@inheritDoc} */ public function equals(ObjectIdentityInterface $identity) { // comparing the identifier with === might lead to problems, so we // waive this restriction return $this->identifier == $identity->getIdentifier() && $this->type === $identity->getType(); } /** * Returns a textual representation of this object identity * * @return string */ public function __toString() { return sprintf('ObjectIdentity(%s, %s)', $this->identifier, $this->type); } } PK]NTA]]#Security/Acl/Domain/AuditLogger.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Model\AuditableEntryInterface; use Symfony\Component\Security\Acl\Model\EntryInterface; use Symfony\Component\Security\Acl\Model\AuditLoggerInterface; /** * Base audit logger implementation * * @author Johannes M. Schmitt */ abstract class AuditLogger implements AuditLoggerInterface { /** * Performs some checks if logging was requested * * @param Boolean $granted * @param EntryInterface $ace */ public function logIfNeeded($granted, EntryInterface $ace) { if (!$ace instanceof AuditableEntryInterface) { return; } if ($granted && $ace->isAuditSuccess()) { $this->doLog($granted, $ace); } elseif (!$granted && $ace->isAuditFailure()) { $this->doLog($granted, $ace); } } /** * This method is only called when logging is needed * * @param Boolean $granted * @param EntryInterface $ace */ abstract protected function doLog($granted, EntryInterface $ace); } PK]C3(Security/Acl/Domain/DoctrineAclCache.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Doctrine\Common\Cache\Cache; use Symfony\Component\Security\Acl\Model\AclCacheInterface; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface; /** * This class is a wrapper around the actual cache implementation. * * @author Johannes M. Schmitt */ class DoctrineAclCache implements AclCacheInterface { const PREFIX = 'sf2_acl_'; private $cache; private $prefix; private $permissionGrantingStrategy; /** * Constructor * * @param Cache $cache * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy * @param string $prefix * * @throws \InvalidArgumentException */ public function __construct(Cache $cache, PermissionGrantingStrategyInterface $permissionGrantingStrategy, $prefix = self::PREFIX) { if (0 === strlen($prefix)) { throw new \InvalidArgumentException('$prefix cannot be empty.'); } $this->cache = $cache; $this->permissionGrantingStrategy = $permissionGrantingStrategy; $this->prefix = $prefix; } /** * {@inheritDoc} */ public function clearCache() { $this->cache->deleteByPrefix($this->prefix); } /** * {@inheritDoc} */ public function evictFromCacheById($aclId) { $lookupKey = $this->getAliasKeyForIdentity($aclId); if (!$this->cache->contains($lookupKey)) { return; } $key = $this->cache->fetch($lookupKey); if ($this->cache->contains($key)) { $this->cache->delete($key); } $this->cache->delete($lookupKey); } /** * {@inheritDoc} */ public function evictFromCacheByIdentity(ObjectIdentityInterface $oid) { $key = $this->getDataKeyByIdentity($oid); if (!$this->cache->contains($key)) { return; } $this->cache->delete($key); } /** * {@inheritDoc} */ public function getFromCacheById($aclId) { $lookupKey = $this->getAliasKeyForIdentity($aclId); if (!$this->cache->contains($lookupKey)) { return null; } $key = $this->cache->fetch($lookupKey); if (!$this->cache->contains($key)) { $this->cache->delete($lookupKey); return null; } return $this->unserializeAcl($this->cache->fetch($key)); } /** * {@inheritDoc} */ public function getFromCacheByIdentity(ObjectIdentityInterface $oid) { $key = $this->getDataKeyByIdentity($oid); if (!$this->cache->contains($key)) { return null; } return $this->unserializeAcl($this->cache->fetch($key)); } /** * {@inheritDoc} */ public function putInCache(AclInterface $acl) { if (null === $acl->getId()) { throw new \InvalidArgumentException('Transient ACLs cannot be cached.'); } if (null !== $parentAcl = $acl->getParentAcl()) { $this->putInCache($parentAcl); } $key = $this->getDataKeyByIdentity($acl->getObjectIdentity()); $this->cache->save($key, serialize($acl)); $this->cache->save($this->getAliasKeyForIdentity($acl->getId()), $key); } /** * Unserializes the ACL. * * @param string $serialized * @return AclInterface */ private function unserializeAcl($serialized) { $acl = unserialize($serialized); if (null !== $parentId = $acl->getParentAcl()) { $parentAcl = $this->getFromCacheById($parentId); if (null === $parentAcl) { return null; } $acl->setParentAcl($parentAcl); } $reflectionProperty = new \ReflectionProperty($acl, 'permissionGrantingStrategy'); $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($acl, $this->permissionGrantingStrategy); $reflectionProperty->setAccessible(false); $aceAclProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Entry', 'acl'); $aceAclProperty->setAccessible(true); foreach ($acl->getObjectAces() as $ace) { $aceAclProperty->setValue($ace, $acl); } foreach ($acl->getClassAces() as $ace) { $aceAclProperty->setValue($ace, $acl); } $aceClassFieldProperty = new \ReflectionProperty($acl, 'classFieldAces'); $aceClassFieldProperty->setAccessible(true); foreach ($aceClassFieldProperty->getValue($acl) as $aces) { foreach ($aces as $ace) { $aceAclProperty->setValue($ace, $acl); } } $aceClassFieldProperty->setAccessible(false); $aceObjectFieldProperty = new \ReflectionProperty($acl, 'objectFieldAces'); $aceObjectFieldProperty->setAccessible(true); foreach ($aceObjectFieldProperty->getValue($acl) as $aces) { foreach ($aces as $ace) { $aceAclProperty->setValue($ace, $acl); } } $aceObjectFieldProperty->setAccessible(false); $aceAclProperty->setAccessible(false); return $acl; } /** * Returns the key for the object identity * * @param ObjectIdentityInterface $oid * @return string */ private function getDataKeyByIdentity(ObjectIdentityInterface $oid) { return $this->prefix.md5($oid->getType()).sha1($oid->getType()) .'_'.md5($oid->getIdentifier()).sha1($oid->getIdentifier()); } /** * Returns the alias key for the object identity key * * @param string $aclId * @return string */ private function getAliasKeyForIdentity($aclId) { return $this->prefix.$aclId; } } PK]0F7Security/Acl/Domain/ObjectIdentityRetrievalStrategy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Exception\InvalidDomainObjectException; use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface; /** * Strategy to be used for retrieving object identities from domain objects * * @author Johannes M. Schmitt */ class ObjectIdentityRetrievalStrategy implements ObjectIdentityRetrievalStrategyInterface { /** * {@inheritDoc} */ public function getObjectIdentity($domainObject) { try { return ObjectIdentity::fromDomainObject($domainObject); } catch (InvalidDomainObjectException $failed) { return null; } } } PK]\! HH Security/Acl/Voter/FieldVote.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Voter; /** * This class is a lightweight wrapper around field vote requests which does * not violate any interface contracts. * * @author Johannes M. Schmitt */ class FieldVote { private $domainObject; private $field; public function __construct($domainObject, $field) { $this->domainObject = $domainObject; $this->field = $field; } public function getDomainObject() { return $this->domainObject; } public function getField() { return $this->field; } } PK]\FSecurity/Acl/Voter/AclVoter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Voter; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Acl\Exception\NoAceFoundException; use Symfony\Component\Security\Acl\Exception\AclNotFoundException; use Symfony\Component\Security\Acl\Model\AclProviderInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; use Symfony\Component\Security\Acl\Permission\PermissionMapInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; /** * This voter can be used as a base class for implementing your own permissions. * * @author Johannes M. Schmitt */ class AclVoter implements VoterInterface { private $aclProvider; private $permissionMap; private $objectIdentityRetrievalStrategy; private $securityIdentityRetrievalStrategy; private $allowIfObjectIdentityUnavailable; private $logger; public function __construct(AclProviderInterface $aclProvider, ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy, SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy, PermissionMapInterface $permissionMap, LoggerInterface $logger = null, $allowIfObjectIdentityUnavailable = true) { $this->aclProvider = $aclProvider; $this->permissionMap = $permissionMap; $this->objectIdentityRetrievalStrategy = $oidRetrievalStrategy; $this->securityIdentityRetrievalStrategy = $sidRetrievalStrategy; $this->logger = $logger; $this->allowIfObjectIdentityUnavailable = $allowIfObjectIdentityUnavailable; } public function supportsAttribute($attribute) { return $this->permissionMap->contains($attribute); } public function vote(TokenInterface $token, $object, array $attributes) { foreach ($attributes as $attribute) { if (null === $masks = $this->permissionMap->getMasks($attribute, $object)) { continue; } if (null === $object) { if (null !== $this->logger) { $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain')); } return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN; } elseif ($object instanceof FieldVote) { $field = $object->getField(); $object = $object->getDomainObject(); } else { $field = null; } if ($object instanceof ObjectIdentityInterface) { $oid = $object; } elseif (null === $oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($object)) { if (null !== $this->logger) { $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain')); } return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN; } if (!$this->supportsClass($oid->getType())) { return self::ACCESS_ABSTAIN; } $sids = $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token); try { $acl = $this->aclProvider->findAcl($oid, $sids); if (null === $field && $acl->isGranted($masks, $sids, false)) { if (null !== $this->logger) { $this->logger->debug('ACL found, permission granted. Voting to grant access'); } return self::ACCESS_GRANTED; } elseif (null !== $field && $acl->isFieldGranted($field, $masks, $sids, false)) { if (null !== $this->logger) { $this->logger->debug('ACL found, permission granted. Voting to grant access'); } return self::ACCESS_GRANTED; } if (null !== $this->logger) { $this->logger->debug('ACL found, insufficient permissions. Voting to deny access.'); } return self::ACCESS_DENIED; } catch (AclNotFoundException $noAcl) { if (null !== $this->logger) { $this->logger->debug('No ACL found for the object identity. Voting to deny access.'); } return self::ACCESS_DENIED; } catch (NoAceFoundException $noAce) { if (null !== $this->logger) { $this->logger->debug('ACL found, no ACE applicable. Voting to deny access.'); } return self::ACCESS_DENIED; } } // no attribute was supported return self::ACCESS_ABSTAIN; } /** * You can override this method when writing a voter for a specific domain * class. * * @param string $class The class name * * @return Boolean */ public function supportsClass($class) { return true; } } PK]}ww-Security/Core/Role/RoleHierarchyInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Role; /** * RoleHierarchyInterface is the interface for a role hierarchy. * * @author Fabien Potencier */ interface RoleHierarchyInterface { /** * Returns an array of all reachable roles by the given ones. * * Reachable roles are the roles directly assigned but also all roles that * are transitively reachable from them in the role hierarchy. * * @param RoleInterface[] $roles An array of directly assigned roles * * @return RoleInterface[] An array of all reachable roles */ public function getReachableRoles(array $roles); } PK]ĦSecurity/Core/Role/Role.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Role; /** * Role is a simple implementation of a RoleInterface where the role is a * string. * * @author Fabien Potencier */ class Role implements RoleInterface { private $role; /** * Constructor. * * @param string $role The role name */ public function __construct($role) { $this->role = (string) $role; } /** * {@inheritdoc} */ public function getRole() { return $this->role; } } PK]XS00%Security/Core/Role/SwitchUserRole.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Role; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * SwitchUserRole is used when the current user temporarily impersonates * another one. * * @author Fabien Potencier */ class SwitchUserRole extends Role { private $source; /** * Constructor. * * @param string $role The role as a string * @param TokenInterface $source The original token */ public function __construct($role, TokenInterface $source) { parent::__construct($role); $this->source = $source; } /** * Returns the original Token. * * @return TokenInterface The original TokenInterface instance */ public function getSource() { return $this->source; } } PK] w??$Security/Core/Role/RoleHierarchy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Role; /** * RoleHierarchy defines a role hierarchy. * * @author Fabien Potencier */ class RoleHierarchy implements RoleHierarchyInterface { private $hierarchy; private $map; /** * Constructor. * * @param array $hierarchy An array defining the hierarchy */ public function __construct(array $hierarchy) { $this->hierarchy = $hierarchy; $this->buildRoleMap(); } /** * {@inheritdoc} */ public function getReachableRoles(array $roles) { $reachableRoles = $roles; foreach ($roles as $role) { if (!isset($this->map[$role->getRole()])) { continue; } foreach ($this->map[$role->getRole()] as $r) { $reachableRoles[] = new Role($r); } } return $reachableRoles; } private function buildRoleMap() { $this->map = array(); foreach ($this->hierarchy as $main => $roles) { $this->map[$main] = $roles; $visited = array(); $additionalRoles = $roles; while ($role = array_shift($additionalRoles)) { if (!isset($this->hierarchy[$role])) { continue; } $visited[] = $role; $this->map[$main] = array_unique(array_merge($this->map[$main], $this->hierarchy[$role])); $additionalRoles = array_merge($additionalRoles, array_diff($this->hierarchy[$role], $visited)); } } } } PK]'c$Security/Core/Role/RoleInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Role; /** * RoleInterface represents a role granted to a user. * * A role must either have a string representation or it needs to be explicitly * supported by at least one AccessDecisionManager. * * @author Fabien Potencier */ interface RoleInterface { /** * Returns the role. * * This method returns a string representation whenever possible. * * When the role cannot be represented with sufficient precision by a * string, it should return null. * * @return string|null A string representation of the role, or null */ public function getRole(); } PK]U4Security/Core/Resources/translations/security.el.xlfnu[ An authentication exception occurred. Συνέβη ένα σφάλμα πιστοποίησης. Authentication credentials could not be found. Τα στοιχεία πιστοποίησης δε βρέθηκαν. Authentication request could not be processed due to a system problem. Το αίτημα πιστοποίησης δε μπορεί να επεξεργαστεί λόγω σφάλματος του συστήματος. Invalid credentials. Λανθασμένα στοιχεία σύνδεσης. Cookie has already been used by someone else. Το Cookie έχει ήδη χρησιμοποιηθεί από κάποιον άλλο. Not privileged to request the resource. Δεν είστε εξουσιοδοτημένος για πρόσβαση στο συγκεκριμένο περιεχόμενο. Invalid CSRF token. Μη έγκυρο CSRF token. Digest nonce has expired. Το digest nonce έχει λήξει. No authentication provider found to support the authentication token. Δε βρέθηκε κάποιος πάροχος πιστοποίησης που να υποστηρίζει το token πιστοποίησης. No session available, it either timed out or cookies are not enabled. Δεν υπάρχει ενεργή σύνοδος (session), είτε έχει λήξει ή τα cookies δεν είναι ενεργοποιημένα. No token could be found. Δεν ήταν δυνατόν να βρεθεί κάποιο token. Username could not be found. Το Username δε βρέθηκε. Account has expired. Ο λογαριασμός έχει λήξει. Credentials have expired. Τα στοιχεία σύνδεσης έχουν λήξει. Account is disabled. Ο λογαριασμός είναι απενεργοποιημένος. Account is locked. Ο λογαριασμός είναι κλειδωμένος. PK]5˙4Security/Core/Resources/translations/security.ua.xlfnu[ An authentication exception occurred. Помилка автентифікації. Authentication credentials could not be found. Автентифікаційні дані не знайдено. Authentication request could not be processed due to a system problem. Запит на автентифікацію не може бути опрацьовано у зв’язку з проблемою в системі. Invalid credentials. Невірні автентифікаційні дані. Cookie has already been used by someone else. Хтось інший вже використав цей сookie. Not privileged to request the resource. Відсутні права на запит цього ресурсу. Invalid CSRF token. Невірний токен CSRF. Digest nonce has expired. Закінчився термін дії одноразового ключа дайджесту. No authentication provider found to support the authentication token. Не знайдено провайдера автентифікації, що підтримує токен автентифікаціії. No session available, it either timed out or cookies are not enabled. Сесія недоступна, її час вийшов, або cookies вимкнено. No token could be found. Токен не знайдено. Username could not be found. Ім’я користувача не знайдено. Account has expired. Термін дії облікового запису вичерпано. Credentials have expired. Термін дії автентифікаційних даних вичерпано. Account is disabled. Обліковий запис відключено. Account is locked. Обліковий запис заблоковано. PK]O 4Security/Core/Resources/translations/security.it.xlfnu[ An authentication exception occurred. Si è verificato un errore di autenticazione. Authentication credentials could not be found. Impossibile trovare le credenziali di autenticazione. Authentication request could not be processed due to a system problem. La richiesta di autenticazione non può essere processata a causa di un errore di sistema. Invalid credentials. Credenziali non valide. Cookie has already been used by someone else. Il cookie è già stato usato da qualcun altro. Not privileged to request the resource. Non hai i privilegi per richiedere questa risorsa. Invalid CSRF token. CSRF token non valido. Digest nonce has expired. Il numero di autenticazione è scaduto. No authentication provider found to support the authentication token. Non è stato trovato un valido fornitore di autenticazione per supportare il token. No session available, it either timed out or cookies are not enabled. Nessuna sessione disponibile, può essere scaduta o i cookie non sono abilitati. No token could be found. Nessun token trovato. Username could not be found. Username non trovato. Account has expired. Account scaduto. Credentials have expired. Credenziali scadute. Account is disabled. L'account è disabilitato. Account is locked. L'account è bloccato. PK]) 4Security/Core/Resources/translations/security.ro.xlfnu[ An authentication exception occurred. A apărut o eroare de autentificare. Authentication credentials could not be found. Informațiile de autentificare nu au fost găsite. Authentication request could not be processed due to a system problem. Sistemul nu a putut procesa cererea de autentificare din cauza unei erori. Invalid credentials. Date de autentificare invalide. Cookie has already been used by someone else. Cookieul este folosit deja de altcineva. Not privileged to request the resource. Permisiuni insuficiente pentru resursa cerută. Invalid CSRF token. Tokenul CSRF este invalid. Digest nonce has expired. Tokenul temporar a expirat. No authentication provider found to support the authentication token. Nu a fost găsit nici un agent de autentificare pentru tokenul specificat. No session available, it either timed out or cookies are not enabled. Sesiunea nu mai este disponibilă, a expirat sau suportul pentru cookieuri nu este activat. No token could be found. Tokenul nu a putut fi găsit. Username could not be found. Numele de utilizator nu a fost găsit. Account has expired. Contul a expirat. Credentials have expired. Datele de autentificare au expirat. Account is disabled. Contul este dezactivat. Account is locked. Contul este blocat. PK]m|JJ9Security/Core/Resources/translations/security.sr_Cyrl.xlfnu[ An authentication exception occurred. Изузетак при аутентификацији. Authentication credentials could not be found. Аутентификациони подаци нису пронађени. Authentication request could not be processed due to a system problem. Захтев за аутентификацију не може бити обрађен због системских проблема. Invalid credentials. Невалидни подаци за аутентификацију. Cookie has already been used by someone else. Колачић је већ искоришћен од стране неког другог. Not privileged to request the resource. Немате права приступа овом ресурсу. Invalid CSRF token. Невалидан CSRF токен. Digest nonce has expired. Време криптографског кључа је истекло. No authentication provider found to support the authentication token. Аутентификациони провајдер за подршку токена није пронађен. No session available, it either timed out or cookies are not enabled. Сесија није доступна, истекла је или су колачићи искључени. No token could be found. Токен не може бити пронађен. Username could not be found. Корисничко име не може бити пронађено. Account has expired. Налог је истекао. Credentials have expired. Подаци за аутентификацију су истекли. Account is disabled. Налог је онемогућен. Account is locked. Налог је закључан. PK]YWg g 9Security/Core/Resources/translations/security.sr_Latn.xlfnu[ An authentication exception occurred. Izuzetak pri autentifikaciji. Authentication credentials could not be found. Autentifikacioni podaci nisu pronađeni. Authentication request could not be processed due to a system problem. Zahtev za autentifikaciju ne može biti obrađen zbog sistemskih problema. Invalid credentials. Nevalidni podaci za autentifikaciju. Cookie has already been used by someone else. Kolačić je već iskorišćen od strane nekog drugog. Not privileged to request the resource. Nemate prava pristupa ovom resursu. Invalid CSRF token. Nevalidan CSRF token. Digest nonce has expired. Vreme kriptografskog ključa je isteklo. No authentication provider found to support the authentication token. Autentifikacioni provajder za podršku tokena nije pronađen. No session available, it either timed out or cookies are not enabled. Sesija nije dostupna, istekla je ili su kolačići isključeni. No token could be found. Token ne može biti pronađen. Username could not be found. Korisničko ime ne može biti pronađeno. Account has expired. Nalog je istekao. Credentials have expired. Podaci za autentifikaciju su istekli. Account is disabled. Nalog je onemogućen. Account is locked. Nalog je zaključan. PK]|H 4Security/Core/Resources/translations/security.hu.xlfnu[ An authentication exception occurred. Hitelesítési hiba lépett fel. Authentication credentials could not be found. Nem találhatók hitelesítési információk. Authentication request could not be processed due to a system problem. A hitelesítési kérést rendszerhiba miatt nem lehet feldolgozni. Invalid credentials. Érvénytelen hitelesítési információk. Cookie has already been used by someone else. Ezt a sütit valaki más már felhasználta. Not privileged to request the resource. Nem rendelkezik az erőforrás eléréséhez szükséges jogosultsággal. Invalid CSRF token. Érvénytelen CSRF token. Digest nonce has expired. A kivonat bélyege (nonce) lejárt. No authentication provider found to support the authentication token. Nem található a hitelesítési tokent támogató hitelesítési szolgáltatás. No session available, it either timed out or cookies are not enabled. Munkamenet nem áll rendelkezésre, túllépte az időkeretet vagy a sütik le vannak tiltva. No token could be found. Nem található token. Username could not be found. A felhasználónév nem található. Account has expired. A fiók lejárt. Credentials have expired. A hitelesítési információk lejártak. Account is disabled. Felfüggesztett fiók. Account is locked. Zárolt fiók. PK]ţ 4Security/Core/Resources/translations/security.ca.xlfnu[ An authentication exception occurred. Ha succeït un error d'autenticació. Authentication credentials could not be found. No s'han trobat les credencials d'autenticació. Authentication request could not be processed due to a system problem. La solicitud d'autenticació no s'ha pogut processar per un problema del sistema. Invalid credentials. Credencials no vàlides. Cookie has already been used by someone else. La cookie ja ha estat utilitzada per una altra persona. Not privileged to request the resource. No té privilegis per solicitar el recurs. Invalid CSRF token. Token CSRF no vàlid. Digest nonce has expired. El vector d'inicialització (digest nonce) ha expirat. No authentication provider found to support the authentication token. No s'ha trobat un proveïdor d'autenticació que suporti el token d'autenticació. No session available, it either timed out or cookies are not enabled. No hi ha sessió disponible, ha expirat o les cookies no estan habilitades. No token could be found. No s'ha trobat cap token. Username could not be found. No s'ha trobat el nom d'usuari. Account has expired. El compte ha expirat. Credentials have expired. Les credencials han expirat. Account is disabled. El compte està deshabilitat. Account is locked. El compte està bloquejat. PK]y 4Security/Core/Resources/translations/security.gl.xlfnu[ An authentication exception occurred. Ocorreu un erro de autenticación. Authentication credentials could not be found. Non se atoparon as credenciais de autenticación. Authentication request could not be processed due to a system problem. A solicitude de autenticación no puido ser procesada debido a un problema do sistema. Invalid credentials. Credenciais non válidas. Cookie has already been used by someone else. A cookie xa foi empregado por outro usuario. Not privileged to request the resource. Non ten privilexios para solicitar o recurso. Invalid CSRF token. Token CSRF non válido. Digest nonce has expired. O vector de inicialización (digest nonce) expirou. No authentication provider found to support the authentication token. Non se atopou un provedor de autenticación que soporte o token de autenticación. No session available, it either timed out or cookies are not enabled. Non hai ningunha sesión dispoñible, expirou ou as cookies non están habilitadas. No token could be found. Non se atopou ningún token. Username could not be found. Non se atopou o nome de usuario. Account has expired. A conta expirou. Credentials have expired. As credenciais expiraron. Account is disabled. A conta está deshabilitada. Account is locked. A conta está bloqueada. PK] 4Security/Core/Resources/translations/security.lb.xlfnu[ An authentication exception occurred. Bei der Authentifikatioun ass e Feeler opgetrueden. Authentication credentials could not be found. Et konnte keng Zouganksdate fonnt ginn. Authentication request could not be processed due to a system problem. D'Ufro fir eng Authentifikatioun konnt wéinst engem Problem vum System net beaarbecht ginn. Invalid credentials. Ongëlteg Zouganksdaten. Cookie has already been used by someone else. De Cookie gouf scho vun engem anere benotzt. Not privileged to request the resource. Keng Rechter fir d'Ressource unzefroen. Invalid CSRF token. Ongëltegen CSRF-Token. Digest nonce has expired. Den eemolege Schlëssel ass ofgelaf. No authentication provider found to support the authentication token. Et gouf keen Authentifizéierungs-Provider fonnt deen den Authentifizéierungs-Token ënnerstëtzt. No session available, it either timed out or cookies are not enabled. Keng Sëtzung disponibel. Entweder ass se ofgelaf oder Cookies sinn net aktivéiert. No token could be found. Et konnt keen Token fonnt ginn. Username could not be found. De Benotzernumm konnt net fonnt ginn. Account has expired. Den Account ass ofgelaf. Credentials have expired. D'Zouganksdate sinn ofgelaf. Account is disabled. De Konto ass deaktivéiert. Account is locked. De Konto ass gespaart. PK]o'N 4Security/Core/Resources/translations/security.de.xlfnu[ An authentication exception occurred. Es ist ein Fehler bei der Authentifikation aufgetreten. Authentication credentials could not be found. Es konnten keine Zugangsdaten gefunden werden. Authentication request could not be processed due to a system problem. Die Authentifikation konnte wegen eines Systemproblems nicht bearbeitet werden. Invalid credentials. Fehlerhafte Zugangsdaten. Cookie has already been used by someone else. Cookie wurde bereits von jemand anderem verwendet. Not privileged to request the resource. Keine Rechte, um die Ressource anzufragen. Invalid CSRF token. Ungültiges CSRF-Token. Digest nonce has expired. Digest nonce ist abgelaufen. No authentication provider found to support the authentication token. Es wurde kein Authentifizierungs-Provider gefunden, der das Authentifizierungs-Token unterstützt. No session available, it either timed out or cookies are not enabled. Keine Session verfügbar, entweder ist diese abgelaufen oder Cookies sind nicht aktiviert. No token could be found. Es wurde kein Token gefunden. Username could not be found. Der Benutzername wurde nicht gefunden. Account has expired. Der Account ist abgelaufen. Credentials have expired. Die Zugangsdaten sind abgelaufen. Account is disabled. Der Account ist deaktiviert. Account is locked. Der Account ist gesperrt. PK].X: : 4Security/Core/Resources/translations/security.en.xlfnu[ An authentication exception occurred. An authentication exception occurred. Authentication credentials could not be found. Authentication credentials could not be found. Authentication request could not be processed due to a system problem. Authentication request could not be processed due to a system problem. Invalid credentials. Invalid credentials. Cookie has already been used by someone else. Cookie has already been used by someone else. Not privileged to request the resource. Not privileged to request the resource. Invalid CSRF token. Invalid CSRF token. Digest nonce has expired. Digest nonce has expired. No authentication provider found to support the authentication token. No authentication provider found to support the authentication token. No session available, it either timed out or cookies are not enabled. No session available, it either timed out or cookies are not enabled. No token could be found. No token could be found. Username could not be found. Username could not be found. Account has expired. Account has expired. Credentials have expired. Credentials have expired. Account is disabled. Account is disabled. Account is locked. Account is locked. PK].W 4Security/Core/Resources/translations/security.no.xlfnu[ An authentication exception occurred. En autentiserings feil har skjedd. Authentication credentials could not be found. Påloggingsinformasjonen kunne ikke bli funnet. Authentication request could not be processed due to a system problem. Autentiserings forespørselen kunne ikke bli prosessert grunnet en system feil. Invalid credentials. Ugyldig påloggingsinformasjonen. Cookie has already been used by someone else. Cookie har allerede blitt brukt av noen andre. Not privileged to request the resource. Ingen tilgang til å be om gitt kilde. Invalid CSRF token. Ugyldig CSRF token. Digest nonce has expired. Digest nonce er utløpt. No authentication provider found to support the authentication token. Ingen autentiserings tilbyder funnet som støtter gitt autentiserings token. No session available, it either timed out or cookies are not enabled. Ingen sesjon tilgjengelig, sesjonen er enten utløpt eller cookies ikke skrudd på. No token could be found. Ingen token kunne bli funnet. Username could not be found. Brukernavn kunne ikke bli funnet. Account has expired. Brukerkonto har utgått. Credentials have expired. Påloggingsinformasjon har utløpt. Account is disabled. Brukerkonto er deaktivert. Account is locked. Brukerkonto er sperret. PK]M-@4Security/Core/Resources/translations/security.fa.xlfnu[ An authentication exception occurred. خطایی هنگام تعیین اعتبار اتفاق افتاد. Authentication credentials could not be found. شرایط تعیین اعتبار پیدا نشد. Authentication request could not be processed due to a system problem. درخواست تعیین اعتبار به دلیل مشکل سیستم قابل بررسی نیست. Invalid credentials. شرایط نامعتبر. Cookie has already been used by someone else. کوکی قبلا برای شخص دیگری استفاده شده است. Not privileged to request the resource. دسترسی لازم برای درخواست این منبع را ندارید. Invalid CSRF token. توکن CSRF معتبر نیست. Digest nonce has expired. Digest nonce منقضی شده است. No authentication provider found to support the authentication token. هیچ ارایه کننده تعیین اعتباری برای ساپورت توکن تعیین اعتبار پیدا نشد. No session available, it either timed out or cookies are not enabled. جلسه‌ای در دسترس نیست. این میتواند یا به دلیل پایان یافتن زمان باشد یا اینکه کوکی ها فعال نیستند. No token could be found. هیچ توکنی پیدا نشد. Username could not be found. نام ‌کاربری پیدا نشد. Account has expired. حساب کاربری منقضی شده است. Credentials have expired. پارامترهای تعیین اعتبار منقضی شده‌اند. Account is disabled. حساب کاربری غیرفعال است. Account is locked. حساب کاربری قفل شده است. PK]z J J 4Security/Core/Resources/translations/security.da.xlfnu[ An authentication exception occurred. En fejl indtraf ved godkendelse. Authentication credentials could not be found. Loginoplysninger kan findes. Authentication request could not be processed due to a system problem. Godkendelsesanmodning kan ikke behandles på grund af et systemfejl. Invalid credentials. Ugyldige loginoplysninger. Cookie has already been used by someone else. Cookie er allerede brugt af en anden. Not privileged to request the resource. Ingen tilladselese at anvende kilden. Invalid CSRF token. Ugyldigt CSRF token. Digest nonce has expired. Digest nonce er udløbet. No authentication provider found to support the authentication token. Ingen godkendelsesudbyder er fundet til understøttelsen af godkendelsestoken. No session available, it either timed out or cookies are not enabled. Ingen session tilgængelig, sessionen er enten udløbet eller cookies er ikke aktiveret. No token could be found. Ingen token kan findes. Username could not be found. Brugernavn kan ikke findes. Account has expired. Brugerkonto er udløbet. Credentials have expired. Loginoplysninger er udløbet. Account is disabled. Brugerkonto er deaktiveret. Account is locked. Brugerkonto er låst. PK]&MЎ 4Security/Core/Resources/translations/security.es.xlfnu[ An authentication exception occurred. Ocurrió un error de autenticación. Authentication credentials could not be found. No se encontraron las credenciales de autenticación. Authentication request could not be processed due to a system problem. La solicitud de autenticación no se pudo procesar debido a un problema del sistema. Invalid credentials. Credenciales no válidas. Cookie has already been used by someone else. La cookie ya ha sido usada por otra persona. Not privileged to request the resource. No tiene privilegios para solicitar el recurso. Invalid CSRF token. Token CSRF no válido. Digest nonce has expired. El vector de inicialización (digest nonce) ha expirado. No authentication provider found to support the authentication token. No se encontró un proveedor de autenticación que soporte el token de autenticación. No session available, it either timed out or cookies are not enabled. No hay ninguna sesión disponible, ha expirado o las cookies no están habilitados. No token could be found. No se encontró ningún token. Username could not be found. No se encontró el nombre de usuario. Account has expired. La cuenta ha expirado. Credentials have expired. Las credenciales han expirado. Account is disabled. La cuenta está deshabilitada. Account is locked. La cuenta está bloqueada. PK]= 7Security/Core/Resources/translations/security.pt_BR.xlfnu[ An authentication exception occurred. Uma exceção ocorreu durante a autenticação. Authentication credentials could not be found. As credenciais de autenticação não foram encontradas. Authentication request could not be processed due to a system problem. A autenticação não pôde ser concluída devido a um problema no sistema. Invalid credentials. Credenciais inválidas. Cookie has already been used by someone else. Este cookie já esta em uso. Not privileged to request the resource. Não possui privilégios o bastante para requisitar este recurso. Invalid CSRF token. Token CSRF inválido. Digest nonce has expired. Digest nonce expirado. No authentication provider found to support the authentication token. Nenhum provedor de autenticação encontrado para suportar o token de autenticação. No session available, it either timed out or cookies are not enabled. Nenhuma sessão disponível, ela expirou ou cookies estão desativados. No token could be found. Nenhum token foi encontrado. Username could not be found. Nome de usuário não encontrado. Account has expired. A conta esta expirada. Credentials have expired. As credenciais estão expiradas. Account is disabled. Conta desativada. Account is locked. A conta esta travada. PK] ( 4Security/Core/Resources/translations/security.cs.xlfnu[ An authentication exception occurred. Při ověřování došlo k chybě. Authentication credentials could not be found. Ověřovací údaje nebyly nalezeny. Authentication request could not be processed due to a system problem. Požadavek na ověření nemohl být zpracován kvůli systémové chybě. Invalid credentials. Neplatné přihlašovací údaje. Cookie has already been used by someone else. Cookie již bylo použité někým jiným. Not privileged to request the resource. Nemáte oprávnění přistupovat k prostředku. Invalid CSRF token. Neplatný CSRF token. Digest nonce has expired. Platnost inicializačního vektoru (digest nonce) vypršela. No authentication provider found to support the authentication token. Poskytovatel pro ověřovací token nebyl nalezen. No session available, it either timed out or cookies are not enabled. Session není k dispozici, vypršela její platnost, nebo jsou zakázané cookies. No token could be found. Token nebyl nalezen. Username could not be found. Přihlašovací jméno nebylo nalezeno. Account has expired. Platnost účtu vypršela. Credentials have expired. Platnost přihlašovacích údajů vypršela. Account is disabled. Účet je zakázaný. Account is locked. Účet je zablokovaný. PK]w=4Security/Core/Resources/translations/security.ru.xlfnu[ An authentication exception occurred. Ошибка аутентификации. Authentication credentials could not be found. Аутентификационные данные не найдены. Authentication request could not be processed due to a system problem. Запрос аутентификации не может быть обработан в связи с проблемой в системе. Invalid credentials. Недействительные аутентификационные данные. Cookie has already been used by someone else. Cookie уже был использован кем-то другим. Not privileged to request the resource. Отсутствуют права на запрос этого ресурса. Invalid CSRF token. Недействительный токен CSRF. Digest nonce has expired. Время действия одноразового ключа дайджеста истекло. No authentication provider found to support the authentication token. Не найден провайдер аутентификации, поддерживающий токен аутентификации. No session available, it either timed out or cookies are not enabled. Сессия не найдена, ее время истекло, либо cookies не включены. No token could be found. Токен не найден. Username could not be found. Имя пользователя не найдено. Account has expired. Время действия учетной записи истекло. Credentials have expired. Время действия аутентификационных данных истекло. Account is disabled. Учетная запись отключена. Account is locked. Учетная запись заблокирована. PK]Tkf4Security/Core/Resources/translations/security.ar.xlfnu[ An authentication exception occurred. حدث خطأ اثناء الدخول. Authentication credentials could not be found. لم استطع العثور على معلومات الدخول. Authentication request could not be processed due to a system problem. لم يكتمل طلب الدخول نتيجه عطل فى النظام. Invalid credentials. معلومات الدخول خاطئة. Cookie has already been used by someone else. ملفات تعريف الارتباط(cookies) تم استخدامها من قبل شخص اخر. Not privileged to request the resource. ليست لديك الصلاحيات الكافية لهذا الطلب. Invalid CSRF token. رمز الموقع غير صحيح. Digest nonce has expired. انتهت صلاحية(digest nonce). No authentication provider found to support the authentication token. لا يوجد معرف للدخول يدعم الرمز المستخدم للدخول. No session available, it either timed out or cookies are not enabled. لا يوجد صلة بينك و بين الموقع اما انها انتهت او ان متصفحك لا يدعم خاصية ملفات تعريف الارتباط (cookies). No token could be found. لم استطع العثور على الرمز. Username could not be found. لم استطع العثور على اسم الدخول. Account has expired. انتهت صلاحية الحساب. Credentials have expired. انتهت صلاحية معلومات الدخول. Account is disabled. الحساب موقوف. Account is locked. الحساب مغلق. PK]'{ { 4Security/Core/Resources/translations/security.tr.xlfnu[ An authentication exception occurred. Bir yetkilendirme istisnası oluştu. Authentication credentials could not be found. Yetkilendirme girdileri bulunamadı. Authentication request could not be processed due to a system problem. Bir sistem hatası nedeniyle yetkilendirme isteği işleme alınamıyor. Invalid credentials. Geçersiz girdiler. Cookie has already been used by someone else. Çerez bir başkası tarafından zaten kullanılmıştı. Not privileged to request the resource. Kaynak talebi için imtiyaz bulunamadı. Invalid CSRF token. Geçersiz CSRF fişi. Digest nonce has expired. Derleme zaman aşımı gerçekleşti. No authentication provider found to support the authentication token. Yetkilendirme fişini destekleyecek yetkilendirme sağlayıcısı bulunamadı. No session available, it either timed out or cookies are not enabled. Oturum bulunamadı, zaman aşımına uğradı veya çerezler etkin değil. No token could be found. Bilet bulunamadı. Username could not be found. Kullanıcı adı bulunamadı. Account has expired. Hesap zaman aşımına uğradı. Credentials have expired. Girdiler zaman aşımına uğradı. Account is disabled. Hesap devre dışı bırakılmış. Account is locked. Hesap kilitlenmiş. PK]de 4Security/Core/Resources/translations/security.fr.xlfnu[ An authentication exception occurred. Une exception d'authentification s'est produite. Authentication credentials could not be found. Les droits d'authentification n'ont pas pu être trouvés. Authentication request could not be processed due to a system problem. La requête d'authentification n'a pas pu être executée à cause d'un problème système. Invalid credentials. Droits invalides. Cookie has already been used by someone else. Le cookie a déjà été utilisé par quelqu'un d'autre. Not privileged to request the resource. Pas de privilèges pour accéder à la ressource. Invalid CSRF token. Jeton CSRF invalide. Digest nonce has expired. Le digest nonce a expiré. No authentication provider found to support the authentication token. Aucun fournisseur d'authentification n'a été trouvé pour supporter le jeton d'authentification. No session available, it either timed out or cookies are not enabled. Pas de session disponible, celle-ci a expiré ou les cookies ne sont pas activés. No token could be found. Aucun jeton n'a pu être trouvé. Username could not be found. Le nom d'utilisateur ne peut pas être trouvé. Account has expired. Le compte a expiré. Credentials have expired. Les droits ont expirés. Account is disabled. Le compte est désactivé. Account is locked. Le compte est bloqué. PK]u^ ^ 4Security/Core/Resources/translations/security.sv.xlfnu[ An authentication exception occurred. Ett autentiseringsfel har inträffat. Authentication credentials could not be found. Uppgifterna för autentisering kunde inte hittas. Authentication request could not be processed due to a system problem. Autentiseringen kunde inte genomföras på grund av systemfel. Invalid credentials. Felaktiga uppgifter. Cookie has already been used by someone else. Cookien har redan använts av någon annan. Not privileged to request the resource. Saknar rättigheter för resursen. Invalid CSRF token. Ogiltig CSRF-token. Digest nonce has expired. Förfallen digest nonce. No authentication provider found to support the authentication token. Ingen leverantör för autentisering hittades för angiven autentiseringstoken. No session available, it either timed out or cookies are not enabled. Ingen session finns tillgänglig, antingen har den förfallit eller är cookies inte aktiverat. No token could be found. Ingen token kunde hittas. Username could not be found. Användarnamnet kunde inte hittas. Account has expired. Kontot har förfallit. Credentials have expired. Uppgifterna har förfallit. Account is disabled. Kontot är inaktiverat. Account is locked. Kontot är låst. PK]d 4Security/Core/Resources/translations/security.pl.xlfnu[ An authentication exception occurred. Wystąpił błąd uwierzytelniania. Authentication credentials could not be found. Dane uwierzytelniania nie zostały znalezione. Authentication request could not be processed due to a system problem. Żądanie uwierzytelniania nie mogło zostać pomyślnie zakończone z powodu problemu z systemem. Invalid credentials. Nieprawidłowe dane. Cookie has already been used by someone else. To ciasteczko jest używane przez kogoś innego. Not privileged to request the resource. Brak uprawnień dla żądania wskazanego zasobu. Invalid CSRF token. Nieprawidłowy token CSRF. Digest nonce has expired. Kod dostępu wygasł. No authentication provider found to support the authentication token. Nie znaleziono mechanizmu uwierzytelniania zdolnego do obsługi przesłanego tokenu. No session available, it either timed out or cookies are not enabled. Brak danych sesji, sesja wygasła lub ciasteczka nie są włączone. No token could be found. Nie znaleziono tokenu. Username could not be found. Użytkownik o podanej nazwie nie istnieje. Account has expired. Konto wygasło. Credentials have expired. Dane uwierzytelniania wygasły. Account is disabled. Konto jest wyłączone. Account is locked. Konto jest zablokowane. PK]UɎd d 4Security/Core/Resources/translations/security.sl.xlfnu[ An authentication exception occurred. Prišlo je do izjeme pri preverjanju avtentikacije. Authentication credentials could not be found. Poverilnic za avtentikacijo ni bilo mogoče najti. Authentication request could not be processed due to a system problem. Zahteve za avtentikacijo ni bilo mogoče izvesti zaradi sistemske težave. Invalid credentials. Neveljavne pravice. Cookie has already been used by someone else. Piškotek je uporabil že nekdo drug. Not privileged to request the resource. Nimate privilegijev za zahtevani vir. Invalid CSRF token. Neveljaven CSRF žeton. Digest nonce has expired. Začasni žeton je potekel. No authentication provider found to support the authentication token. Ponudnika avtentikacije za podporo prijavnega žetona ni bilo mogoče najti. No session available, it either timed out or cookies are not enabled. Seja ni na voljo, ali je potekla ali pa piškotki niso omogočeni. No token could be found. Žetona ni bilo mogoče najti. Username could not be found. Uporabniškega imena ni bilo mogoče najti. Account has expired. Račun je potekel. Credentials have expired. Poverilnice so potekle. Account is disabled. Račun je onemogočen. Account is locked. Račun je zaklenjen. PK]#@y y 7Security/Core/Resources/translations/security.pt_PT.xlfnu[ An authentication exception occurred. Ocorreu um excepção durante a autenticação. Authentication credentials could not be found. As credenciais de autenticação não foram encontradas. Authentication request could not be processed due to a system problem. O pedido de autenticação não foi concluído devido a um problema no sistema. Invalid credentials. Credenciais inválidas. Cookie has already been used by someone else. Este cookie já esta em uso. Not privileged to request the resource. Não possui privilégios para aceder a este recurso. Invalid CSRF token. Token CSRF inválido. Digest nonce has expired. Digest nonce expirado. No authentication provider found to support the authentication token. Nenhum fornecedor de autenticação encontrado para suportar o token de autenticação. No session available, it either timed out or cookies are not enabled. Não existe sessão disponível, esta expirou ou os cookies estão desativados. No token could be found. O token não foi encontrado. Username could not be found. Nome de utilizador não encontrado. Account has expired. A conta expirou. Credentials have expired. As credenciais expiraram. Account is disabled. Conta desativada. Account is locked. A conta esta trancada. PK]pU 4Security/Core/Resources/translations/security.nl.xlfnu[ An authentication exception occurred. Er heeft zich een authenticatieprobleem voorgedaan. Authentication credentials could not be found. Authenticatiegegevens konden niet worden gevonden. Authentication request could not be processed due to a system problem. Authenticatieaanvraag kon niet worden verwerkt door een technisch probleem. Invalid credentials. Ongeldige inloggegevens. Cookie has already been used by someone else. Cookie is al door een ander persoon gebruikt. Not privileged to request the resource. Onvoldoende rechten om de aanvraag te verwerken. Invalid CSRF token. CSRF-code is ongeldig. Digest nonce has expired. Serverauthenticatiesleutel (digest nonce) is verlopen. No authentication provider found to support the authentication token. Geen authenticatieprovider gevonden die de authenticatietoken ondersteunt. No session available, it either timed out or cookies are not enabled. Geen sessie beschikbaar, mogelijk is deze verlopen of cookies zijn uitgeschakeld. No token could be found. Er kon geen authenticatietoken worden gevonden. Username could not be found. Gebruikersnaam kon niet worden gevonden. Account has expired. Account is verlopen. Credentials have expired. Authenticatiegegevens zijn verlopen. Account is disabled. Account is gedeactiveerd. Account is locked. Account is geblokkeerd. PK]ق 4Security/Core/Resources/translations/security.sk.xlfnu[ An authentication exception occurred. Pri overovaní došlo k chybe. Authentication credentials could not be found. Overovacie údaje neboli nájdené. Authentication request could not be processed due to a system problem. Požiadavok na overenie nemohol byť spracovaný kvôli systémovej chybe. Invalid credentials. Neplatné prihlasovacie údaje. Cookie has already been used by someone else. Cookie už bolo použité niekým iným. Not privileged to request the resource. Nemáte oprávnenie pristupovať k prostriedku. Invalid CSRF token. Neplatný CSRF token. Digest nonce has expired. Platnosť inicializačného vektoru (digest nonce) skončila. No authentication provider found to support the authentication token. Poskytovateľ pre overovací token nebol nájdený. No session available, it either timed out or cookies are not enabled. Session nie je k dispozíci, vypršala jej platnosť, alebo sú zakázané cookies. No token could be found. Token nebol nájdený. Username could not be found. Prihlasovacie meno nebolo nájdené. Account has expired. Platnosť účtu skončila. Credentials have expired. Platnosť prihlasovacích údajov skončila. Account is disabled. Účet je zakázaný. Account is locked. Účet je zablokovaný. PK]S*Security/Core/SecurityContextInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * The SecurityContextInterface. * * @author Johannes M. Schmitt */ interface SecurityContextInterface { const ACCESS_DENIED_ERROR = '_security.403_error'; const AUTHENTICATION_ERROR = '_security.last_error'; const LAST_USERNAME = '_security.last_username'; /** * Returns the current security token. * * @return TokenInterface|null A TokenInterface instance or null if no authentication information is available */ public function getToken(); /** * Sets the authentication token. * * @param TokenInterface $token A TokenInterface token, or null if no further authentication information should be stored */ public function setToken(TokenInterface $token = null); /** * Checks if the attributes are granted against the current authentication token and optionally supplied object. * * @param mixed $attributes * @param mixed $object * * @return Boolean */ public function isGranted($attributes, $object = null); } PK]ѵ^2Security/Core/Authorization/ExpressionLanguage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization; use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; /** * Adds some function to the default ExpressionLanguage. * * @author Fabien Potencier */ class ExpressionLanguage extends BaseExpressionLanguage { protected function registerFunctions() { parent::registerFunctions(); $this->register('is_anonymous', function () { return '$trust_resolver->isAnonymous($token)'; }, function (array $variables) { return $variables['trust_resolver']->isAnonymous($variables['token']); }); $this->register('is_authenticated', function () { return '$token && !$trust_resolver->isAnonymous($token)'; }, function (array $variables) { return $variables['token'] && !$variables['trust_resolver']->isAnonymous($variables['token']); }); $this->register('is_fully_authenticated', function () { return '$trust_resolver->isFullFledged($token)'; }, function (array $variables) { return $variables['trust_resolver']->isFullFledged($variables['token']); }); $this->register('is_remember_me', function () { return '$trust_resolver->isRememberMe($token)'; }, function (array $variables) { return $variables['trust_resolver']->isRememberMe($variables['token']); }); $this->register('has_role', function ($role) { return sprintf('in_array(%s, $roles)', $role); }, function (array $variables, $role) { return in_array($role, $variables['roles']); }); } } PK]:22>Security/Core/Authorization/AccessDecisionManagerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * AccessDecisionManagerInterface makes authorization decisions. * * @author Fabien Potencier */ interface AccessDecisionManagerInterface { /** * Decides whether the access is possible or not. * * @param TokenInterface $token A TokenInterface instance * @param array $attributes An array of attributes associated with the method being invoked * @param object $object The object to secure * * @return Boolean true if the access is granted, false otherwise */ public function decide(TokenInterface $token, array $attributes, $object = null); /** * Checks if the access decision manager supports the given attribute. * * @param string $attribute An attribute * * @return Boolean true if this decision manager supports the attribute, false otherwise */ public function supportsAttribute($attribute); /** * Checks if the access decision manager supports the given class. * * @param string $class A class name * * @return true if this decision manager can process the class */ public function supportsClass($class); } PK]>4Security/Core/Authorization/Voter/VoterInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * VoterInterface is the interface implemented by all voters. * * @author Fabien Potencier */ interface VoterInterface { const ACCESS_GRANTED = 1; const ACCESS_ABSTAIN = 0; const ACCESS_DENIED = -1; /** * Checks if the voter supports the given attribute. * * @param string $attribute An attribute * * @return Boolean true if this Voter supports the attribute, false otherwise */ public function supportsAttribute($attribute); /** * Checks if the voter supports the given class. * * @param string $class A class name * * @return Boolean true if this Voter can process the class */ public function supportsClass($class); /** * Returns the vote for the given parameters. * * This method must return one of the following constants: * ACCESS_GRANTED, ACCESS_DENIED, or ACCESS_ABSTAIN. * * @param TokenInterface $token A TokenInterface instance * @param object $object The object to secure * @param array $attributes An array of attributes associated with the method being invoked * * @return integer either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED */ public function vote(TokenInterface $token, $object, array $attributes); } PK]`c 5Security/Core/Authorization/Voter/ExpressionVoter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; use Symfony\Component\Security\Core\Authorization\ExpressionLanguage; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\HttpFoundation\Request; /** * ExpressionVoter votes based on the evaluation of an expression. * * @author Fabien Potencier */ class ExpressionVoter implements VoterInterface { private $expressionLanguage; private $trustResolver; private $roleHierarchy; /** * Constructor. * * @param ExpressionLanguage $expressionLanguage */ public function __construct(ExpressionLanguage $expressionLanguage, AuthenticationTrustResolverInterface $trustResolver, RoleHierarchyInterface $roleHierarchy = null) { $this->expressionLanguage = $expressionLanguage; $this->trustResolver = $trustResolver; $this->roleHierarchy = $roleHierarchy; } /** * {@inheritdoc} */ public function supportsAttribute($attribute) { return $attribute instanceof Expression; } /** * {@inheritdoc} */ public function supportsClass($class) { return true; } /** * {@inheritdoc} */ public function vote(TokenInterface $token, $object, array $attributes) { $result = VoterInterface::ACCESS_ABSTAIN; $variables = null; foreach ($attributes as $attribute) { if (!$this->supportsAttribute($attribute)) { continue; } if (null === $variables) { $variables = $this->getVariables($token, $object); } $result = VoterInterface::ACCESS_DENIED; if ($this->expressionLanguage->evaluate($attribute, $variables)) { return VoterInterface::ACCESS_GRANTED; } } return $result; } private function getVariables(TokenInterface $token, $object) { if (null !== $this->roleHierarchy) { $roles = $this->roleHierarchy->getReachableRoles($token->getRoles()); } else { $roles = $token->getRoles(); } $variables = array( 'token' => $token, 'user' => $token->getUser(), 'object' => $object, 'roles' => array_map(function ($role) { return $role->getRole(); }, $roles), 'trust_resolver' => $this->trustResolver, ); // this is mainly to propose a better experience when the expression is used // in an access control rule, as the developer does not know that it's going // to be handled by this voter if ($object instanceof Request) { $variables['request'] = $object; } return $variables; } } PK]З~/Security/Core/Authorization/Voter/RoleVoter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * RoleVoter votes if any attribute starts with a given prefix. * * @author Fabien Potencier */ class RoleVoter implements VoterInterface { private $prefix; /** * Constructor. * * @param string $prefix The role prefix */ public function __construct($prefix = 'ROLE_') { $this->prefix = $prefix; } /** * {@inheritdoc} */ public function supportsAttribute($attribute) { return 0 === strpos($attribute, $this->prefix); } /** * {@inheritdoc} */ public function supportsClass($class) { return true; } /** * {@inheritdoc} */ public function vote(TokenInterface $token, $object, array $attributes) { $result = VoterInterface::ACCESS_ABSTAIN; $roles = $this->extractRoles($token); foreach ($attributes as $attribute) { if (!$this->supportsAttribute($attribute)) { continue; } $result = VoterInterface::ACCESS_DENIED; foreach ($roles as $role) { if ($attribute === $role->getRole()) { return VoterInterface::ACCESS_GRANTED; } } } return $result; } protected function extractRoles(TokenInterface $token) { return $token->getRoles(); } } PK]X,m  8Security/Core/Authorization/Voter/AuthenticatedVoter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * AuthenticatedVoter votes if an attribute like IS_AUTHENTICATED_FULLY, * IS_AUTHENTICATED_REMEMBERED, or IS_AUTHENTICATED_ANONYMOUSLY is present. * * This list is most restrictive to least restrictive checking. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class AuthenticatedVoter implements VoterInterface { const IS_AUTHENTICATED_FULLY = 'IS_AUTHENTICATED_FULLY'; const IS_AUTHENTICATED_REMEMBERED = 'IS_AUTHENTICATED_REMEMBERED'; const IS_AUTHENTICATED_ANONYMOUSLY = 'IS_AUTHENTICATED_ANONYMOUSLY'; private $authenticationTrustResolver; /** * Constructor. * * @param AuthenticationTrustResolverInterface $authenticationTrustResolver */ public function __construct(AuthenticationTrustResolverInterface $authenticationTrustResolver) { $this->authenticationTrustResolver = $authenticationTrustResolver; } /** * {@inheritdoc} */ public function supportsAttribute($attribute) { return null !== $attribute && (self::IS_AUTHENTICATED_FULLY === $attribute || self::IS_AUTHENTICATED_REMEMBERED === $attribute || self::IS_AUTHENTICATED_ANONYMOUSLY === $attribute); } /** * {@inheritdoc} */ public function supportsClass($class) { return true; } /** * {@inheritdoc} */ public function vote(TokenInterface $token, $object, array $attributes) { $result = VoterInterface::ACCESS_ABSTAIN; foreach ($attributes as $attribute) { if (!$this->supportsAttribute($attribute)) { continue; } $result = VoterInterface::ACCESS_DENIED; if (self::IS_AUTHENTICATED_FULLY === $attribute && $this->authenticationTrustResolver->isFullFledged($token)) { return VoterInterface::ACCESS_GRANTED; } if (self::IS_AUTHENTICATED_REMEMBERED === $attribute && ($this->authenticationTrustResolver->isRememberMe($token) || $this->authenticationTrustResolver->isFullFledged($token))) { return VoterInterface::ACCESS_GRANTED; } if (self::IS_AUTHENTICATED_ANONYMOUSLY === $attribute && ($this->authenticationTrustResolver->isAnonymous($token) || $this->authenticationTrustResolver->isRememberMe($token) || $this->authenticationTrustResolver->isFullFledged($token))) { return VoterInterface::ACCESS_GRANTED; } } return $result; } } PK]~f8Security/Core/Authorization/Voter/RoleHierarchyVoter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; /** * RoleHierarchyVoter uses a RoleHierarchy to determine the roles granted to * the user before voting. * * @author Fabien Potencier */ class RoleHierarchyVoter extends RoleVoter { private $roleHierarchy; public function __construct(RoleHierarchyInterface $roleHierarchy, $prefix = 'ROLE_') { $this->roleHierarchy = $roleHierarchy; parent::__construct($prefix); } /** * {@inheritdoc} */ protected function extractRoles(TokenInterface $token) { return $this->roleHierarchy->getReachableRoles($token->getRoles()); } } PK]m25Security/Core/Authorization/AccessDecisionManager.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * AccessDecisionManager is the base class for all access decision managers * that use decision voters. * * @author Fabien Potencier */ class AccessDecisionManager implements AccessDecisionManagerInterface { private $voters; private $strategy; private $allowIfAllAbstainDecisions; private $allowIfEqualGrantedDeniedDecisions; /** * Constructor. * * @param VoterInterface[] $voters An array of VoterInterface instances * @param string $strategy The vote strategy * @param Boolean $allowIfAllAbstainDecisions Whether to grant access if all voters abstained or not * @param Boolean $allowIfEqualGrantedDeniedDecisions Whether to grant access if result are equals * * @throws \InvalidArgumentException */ public function __construct(array $voters, $strategy = 'affirmative', $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true) { if (!$voters) { throw new \InvalidArgumentException('You must at least add one voter.'); } $strategyMethod = 'decide'.ucfirst($strategy); if (!is_callable(array($this, $strategyMethod))) { throw new \InvalidArgumentException(sprintf('The strategy "%s" is not supported.', $strategy)); } $this->voters = $voters; $this->strategy = $strategyMethod; $this->allowIfAllAbstainDecisions = (Boolean) $allowIfAllAbstainDecisions; $this->allowIfEqualGrantedDeniedDecisions = (Boolean) $allowIfEqualGrantedDeniedDecisions; } /** * {@inheritdoc} */ public function decide(TokenInterface $token, array $attributes, $object = null) { return $this->{$this->strategy}($token, $attributes, $object); } /** * {@inheritdoc} */ public function supportsAttribute($attribute) { foreach ($this->voters as $voter) { if ($voter->supportsAttribute($attribute)) { return true; } } return false; } /** * {@inheritdoc} */ public function supportsClass($class) { foreach ($this->voters as $voter) { if ($voter->supportsClass($class)) { return true; } } return false; } /** * Grants access if any voter returns an affirmative response. * * If all voters abstained from voting, the decision will be based on the * allowIfAllAbstainDecisions property value (defaults to false). */ private function decideAffirmative(TokenInterface $token, array $attributes, $object = null) { $deny = 0; foreach ($this->voters as $voter) { $result = $voter->vote($token, $object, $attributes); switch ($result) { case VoterInterface::ACCESS_GRANTED: return true; case VoterInterface::ACCESS_DENIED: ++$deny; break; default: break; } } if ($deny > 0) { return false; } return $this->allowIfAllAbstainDecisions; } /** * Grants access if there is consensus of granted against denied responses. * * Consensus means majority-rule (ignoring abstains) rather than unanimous * agreement (ignoring abstains). If you require unanimity, see * UnanimousBased. * * If there were an equal number of grant and deny votes, the decision will * be based on the allowIfEqualGrantedDeniedDecisions property value * (defaults to true). * * If all voters abstained from voting, the decision will be based on the * allowIfAllAbstainDecisions property value (defaults to false). */ private function decideConsensus(TokenInterface $token, array $attributes, $object = null) { $grant = 0; $deny = 0; $abstain = 0; foreach ($this->voters as $voter) { $result = $voter->vote($token, $object, $attributes); switch ($result) { case VoterInterface::ACCESS_GRANTED: ++$grant; break; case VoterInterface::ACCESS_DENIED: ++$deny; break; default: ++$abstain; break; } } if ($grant > $deny) { return true; } if ($deny > $grant) { return false; } if ($grant == $deny && $grant != 0) { return $this->allowIfEqualGrantedDeniedDecisions; } return $this->allowIfAllAbstainDecisions; } /** * Grants access if only grant (or abstain) votes were received. * * If all voters abstained from voting, the decision will be based on the * allowIfAllAbstainDecisions property value (defaults to false). */ private function decideUnanimous(TokenInterface $token, array $attributes, $object = null) { $grant = 0; foreach ($attributes as $attribute) { foreach ($this->voters as $voter) { $result = $voter->vote($token, $object, array($attribute)); switch ($result) { case VoterInterface::ACCESS_GRANTED: ++$grant; break; case VoterInterface::ACCESS_DENIED: return false; default: break; } } } // no deny votes if ($grant > 0) { return true; } return $this->allowIfAllAbstainDecisions; } } PK]D$.."Security/Core/User/UserChecker.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Exception\CredentialsExpiredException; use Symfony\Component\Security\Core\Exception\LockedException; use Symfony\Component\Security\Core\Exception\DisabledException; use Symfony\Component\Security\Core\Exception\AccountExpiredException; /** * UserChecker checks the user account flags. * * @author Fabien Potencier */ class UserChecker implements UserCheckerInterface { /** * {@inheritdoc} */ public function checkPreAuth(UserInterface $user) { if (!$user instanceof AdvancedUserInterface) { return; } if (!$user->isAccountNonLocked()) { $ex = new LockedException('User account is locked.'); $ex->setUser($user); throw $ex; } if (!$user->isEnabled()) { $ex = new DisabledException('User account is disabled.'); $ex->setUser($user); throw $ex; } if (!$user->isAccountNonExpired()) { $ex = new AccountExpiredException('User account has expired.'); $ex->setUser($user); throw $ex; } } /** * {@inheritdoc} */ public function checkPostAuth(UserInterface $user) { if (!$user instanceof AdvancedUserInterface) { return; } if (!$user->isCredentialsNonExpired()) { $ex = new CredentialsExpiredException('User credentials have expired.'); $ex->setUser($user); throw $ex; } } } PK]1G G Security/Core/User/User.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; /** * User is the user implementation used by the in-memory user provider. * * This should not be used for anything else. * * @author Fabien Potencier */ final class User implements AdvancedUserInterface { private $username; private $password; private $enabled; private $accountNonExpired; private $credentialsNonExpired; private $accountNonLocked; private $roles; public function __construct($username, $password, array $roles = array(), $enabled = true, $userNonExpired = true, $credentialsNonExpired = true, $userNonLocked = true) { if (empty($username)) { throw new \InvalidArgumentException('The username cannot be empty.'); } $this->username = $username; $this->password = $password; $this->enabled = $enabled; $this->accountNonExpired = $userNonExpired; $this->credentialsNonExpired = $credentialsNonExpired; $this->accountNonLocked = $userNonLocked; $this->roles = $roles; } /** * {@inheritdoc} */ public function getRoles() { return $this->roles; } /** * {@inheritdoc} */ public function getPassword() { return $this->password; } /** * {@inheritdoc} */ public function getSalt() { return null; } /** * {@inheritdoc} */ public function getUsername() { return $this->username; } /** * {@inheritdoc} */ public function isAccountNonExpired() { return $this->accountNonExpired; } /** * {@inheritdoc} */ public function isAccountNonLocked() { return $this->accountNonLocked; } /** * {@inheritdoc} */ public function isCredentialsNonExpired() { return $this->credentialsNonExpired; } /** * {@inheritdoc} */ public function isEnabled() { return $this->enabled; } /** * {@inheritdoc} */ public function eraseCredentials() { } } PK]+Security/Core/User/UserCheckerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; /** * UserCheckerInterface checks user account when authentication occurs. * * This should not be used to make authentication decisions. * * @author Fabien Potencier */ interface UserCheckerInterface { /** * Checks the user account before authentication. * * @param UserInterface $user a UserInterface instance */ public function checkPreAuth(UserInterface $user); /** * Checks the user account after authentication. * * @param UserInterface $user a UserInterface instance */ public function checkPostAuth(UserInterface $user); } PK]/!  +Security/Core/User/InMemoryUserProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; /** * InMemoryUserProvider is a simple non persistent user provider. * * Useful for testing, demonstration, prototyping, and for simple needs * (a backend with a unique admin for instance) * * @author Fabien Potencier */ class InMemoryUserProvider implements UserProviderInterface { private $users; /** * Constructor. * * The user array is a hash where the keys are usernames and the values are * an array of attributes: 'password', 'enabled', and 'roles'. * * @param array $users An array of users */ public function __construct(array $users = array()) { foreach ($users as $username => $attributes) { $password = isset($attributes['password']) ? $attributes['password'] : null; $enabled = isset($attributes['enabled']) ? $attributes['enabled'] : true; $roles = isset($attributes['roles']) ? $attributes['roles'] : array(); $user = new User($username, $password, $roles, $enabled, true, true, true); $this->createUser($user); } } /** * Adds a new User to the provider. * * @param UserInterface $user A UserInterface instance * * @throws \LogicException */ public function createUser(UserInterface $user) { if (isset($this->users[strtolower($user->getUsername())])) { throw new \LogicException('Another user with the same username already exists.'); } $this->users[strtolower($user->getUsername())] = $user; } /** * {@inheritdoc} */ public function loadUserByUsername($username) { if (!isset($this->users[strtolower($username)])) { $ex = new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username)); $ex->setUsername($username); throw $ex; } $user = $this->users[strtolower($username)]; return new User($user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled(), $user->isAccountNonExpired(), $user->isCredentialsNonExpired(), $user->isAccountNonLocked()); } /** * {@inheritDoc} */ public function refreshUser(UserInterface $user) { if (!$user instanceof User) { throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); } return $this->loadUserByUsername($user->getUsername()); } /** * {@inheritDoc} */ public function supportsClass($class) { return $class === 'Symfony\Component\Security\Core\User\User'; } } PK]svW W ,Security/Core/User/UserProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; /** * Represents a class that loads UserInterface objects from some source for the authentication system. * * In a typical authentication configuration, a username (i.e. some unique * user identifier) credential enters the system (via form login, or any * method). The user provider that is configured with that authentication * method is asked to load the UserInterface object for the given username * (via loadUserByUsername) so that the rest of the process can continue. * * Internally, a user provider can load users from any source (databases, * configuration, web service). This is totally independent of how the authentication * information is submitted or what the UserInterface object looks like. * * @see UserInterface * * @author Fabien Potencier */ interface UserProviderInterface { /** * Loads the user for the given username. * * This method must throw UsernameNotFoundException if the user is not * found. * * @param string $username The username * * @return UserInterface * * @see UsernameNotFoundException * * @throws UsernameNotFoundException if the user is not found * */ public function loadUserByUsername($username); /** * Refreshes the user for the account interface. * * It is up to the implementation to decide if the user data should be * totally reloaded (e.g. from the database), or if the UserInterface * object can just be merged into some internal array of users / identity * map. * @param UserInterface $user * * @return UserInterface * * @throws UnsupportedUserException if the account is not supported */ public function refreshUser(UserInterface $user); /** * Whether this provider supports the given user class * * @param string $class * * @return Boolean */ public function supportsClass($class); } PK]6bY Y ,Security/Core/User/AdvancedUserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Exception\AccountStatusException; use Symfony\Component\Security\Core\Exception\AccountExpiredException; use Symfony\Component\Security\Core\Exception\LockedException; use Symfony\Component\Security\Core\Exception\CredentialsExpiredException; use Symfony\Component\Security\Core\Exception\DisabledException; /** * Adds extra features to a user class related to account status flags. * * This interface can be implemented in place of UserInterface if you'd like * the authentication system to consider different account status flags * during authentication. If any of the methods in this interface return * false, authentication will fail. * * If you need to perform custom logic for any of these situations, then * you will need to register an exception listener and watch for the specific * exception instances thrown in each case. All exceptions are a subclass * of AccountStatusException * * @see UserInterface * @see AccountStatusException * * @author Fabien Potencier */ interface AdvancedUserInterface extends UserInterface { /** * Checks whether the user's account has expired. * * Internally, if this method returns false, the authentication system * will throw an AccountExpiredException and prevent login. * * @return Boolean true if the user's account is non expired, false otherwise * * @see AccountExpiredException */ public function isAccountNonExpired(); /** * Checks whether the user is locked. * * Internally, if this method returns false, the authentication system * will throw a LockedException and prevent login. * * @return Boolean true if the user is not locked, false otherwise * * @see LockedException */ public function isAccountNonLocked(); /** * Checks whether the user's credentials (password) has expired. * * Internally, if this method returns false, the authentication system * will throw a CredentialsExpiredException and prevent login. * * @return Boolean true if the user's credentials are non expired, false otherwise * * @see CredentialsExpiredException */ public function isCredentialsNonExpired(); /** * Checks whether the user is enabled. * * Internally, if this method returns false, the authentication system * will throw a DisabledException and prevent login. * * @return Boolean true if the user is enabled, false otherwise * * @see DisabledException */ public function isEnabled(); } PK] $Security/Core/User/UserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Role\Role; /** * Represents the interface that all user classes must implement. * * This interface is useful because the authentication layer can deal with * the object through its lifecycle, using the object to get the encoded * password (for checking against a submitted password), assigning roles * and so on. * * Regardless of how your user are loaded or where they come from (a database, * configuration, web service, etc), you will have a class that implements * this interface. Objects that implement this interface are created and * loaded by different objects that implement UserProviderInterface * * @see UserProviderInterface * @see AdvancedUserInterface * * @author Fabien Potencier */ interface UserInterface { /** * Returns the roles granted to the user. * * * public function getRoles() * { * return array('ROLE_USER'); * } * * * Alternatively, the roles might be stored on a ``roles`` property, * and populated in any number of different ways when the user object * is created. * * @return Role[] The user roles */ public function getRoles(); /** * Returns the password used to authenticate the user. * * This should be the encoded password. On authentication, a plain-text * password will be salted, encoded, and then compared to this value. * * @return string The password */ public function getPassword(); /** * Returns the salt that was originally used to encode the password. * * This can return null if the password was not encoded using a salt. * * @return string|null The salt */ public function getSalt(); /** * Returns the username used to authenticate the user. * * @return string The username */ public function getUsername(); /** * Removes sensitive data from the user. * * This is important if, at any given point, sensitive information like * the plain-text password is stored on this object. */ public function eraseCredentials(); } PK]^ (Security/Core/User/ChainUserProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; /** * Chain User Provider. * * This provider calls several leaf providers in a chain until one is able to * handle the request. * * @author Johannes M. Schmitt */ class ChainUserProvider implements UserProviderInterface { private $providers; public function __construct(array $providers) { $this->providers = $providers; } /** * @return array */ public function getProviders() { return $this->providers; } /** * {@inheritDoc} */ public function loadUserByUsername($username) { foreach ($this->providers as $provider) { try { return $provider->loadUserByUsername($username); } catch (UsernameNotFoundException $notFound) { // try next one } } $ex = new UsernameNotFoundException(sprintf('There is no user with name "%s".', $username)); $ex->setUsername($username); throw $ex; } /** * {@inheritDoc} */ public function refreshUser(UserInterface $user) { $supportedUserFound = false; foreach ($this->providers as $provider) { try { return $provider->refreshUser($user); } catch (UnsupportedUserException $unsupported) { // try next one } catch (UsernameNotFoundException $notFound) { $supportedUserFound = true; // try next one } } if ($supportedUserFound) { $ex = new UsernameNotFoundException(sprintf('There is no user with name "%s".', $user->getUsername())); $ex->setUsername($user->getUsername()); throw $ex; } else { throw new UnsupportedUserException(sprintf('The account "%s" is not supported.', get_class($user))); } } /** * {@inheritDoc} */ public function supportsClass($class) { foreach ($this->providers as $provider) { if ($provider->supportsClass($class)) { return true; } } return false; } } PK]//)Security/Core/User/EquatableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; /** * EquatableInterface used to test if two objects are equal in security * and re-authentication context. * * @author Dariusz Górecki */ interface EquatableInterface { /** * The equality comparison should neither be done by referential equality * nor by comparing identities (i.e. getId() === getId()). * * However, you do not need to compare every attribute, but only those that * are relevant for assessing whether re-authentication is required. * * Also implementation should consider that $user instance may implement * the extended user interface `AdvancedUserInterface`. * * @param UserInterface $user * * @return Boolean */ public function isEqualTo(UserInterface $user); } PK] ,Security/Core/Util/SecureRandomInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Util; /** * Interface that needs to be implemented by all secure random number generators. * * @author Fabien Potencier */ interface SecureRandomInterface { /** * Generates the specified number of secure random bytes. * * @param integer $nbBytes * * @return string */ public function nextBytes($nbBytes); } PK]T,,!Security/Core/Util/ClassUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Util; /** * Class related functionality for objects that * might or might not be proxy objects at the moment. * * @see Doctrine\Common\Util\ClassUtils * * @author Benjamin Eberlei * @author Johannes Schmitt */ class ClassUtils { /** * Marker for Proxy class names. * * @var string */ const MARKER = '__CG__'; /** * Length of the proxy marker * * @var int */ const MARKER_LENGTH = 6; /** * This class should not be instantiated */ private function __construct() {} /** * Gets the real class name of a class name that could be a proxy. * * @param string|object * @return string */ public static function getRealClass($object) { $class = is_object($object) ? get_class($object) : $object; if (false === $pos = strrpos($class, '\\'.self::MARKER.'\\')) { return $class; } return substr($class, $pos + self::MARKER_LENGTH + 2); } } PK]Ua"Security/Core/Util/StringUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Util; /** * String utility functions. * * @author Fabien Potencier */ class StringUtils { /** * This class should not be instantiated */ private function __construct() {} /** * Compares two strings. * * This method implements a constant-time algorithm to compare strings. * * @param string $knownString The string of known length to compare against * @param string $userInput The string that the user can control * * @return Boolean true if the two strings are the same, false otherwise */ public static function equals($knownString, $userInput) { // Prevent issues if string length is 0 $knownString .= chr(0); $userInput .= chr(0); $knownLen = strlen($knownString); $userLen = strlen($userInput); // Set the result to the difference between the lengths $result = $knownLen - $userLen; // Note that we ALWAYS iterate over the user-supplied length // This is to prevent leaking length information for ($i = 0; $i < $userLen; $i++) { // Using % here is a trick to prevent notices // It's safe, since if the lengths are different // $result is already non-0 $result |= (ord($knownString[$i % $knownLen]) ^ ord($userInput[$i])); } // They are only identical strings if $result is exactly 0... return 0 === $result; } } PK]Õ  #Security/Core/Util/SecureRandom.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Util; use Psr\Log\LoggerInterface; /** * A secure random number generator implementation. * * @author Fabien Potencier * @author Johannes M. Schmitt */ final class SecureRandom implements SecureRandomInterface { private $logger; private $useOpenSsl; private $seed; private $seedUpdated; private $seedLastUpdatedAt; private $seedFile; /** * Constructor. * * Be aware that a guessable seed will severely compromise the PRNG * algorithm that is employed. * * @param string $seedFile * @param LoggerInterface $logger */ public function __construct($seedFile = null, LoggerInterface $logger = null) { $this->seedFile = $seedFile; $this->logger = $logger; // determine whether to use OpenSSL if (defined('PHP_WINDOWS_VERSION_BUILD') && version_compare(PHP_VERSION, '5.3.4', '<')) { $this->useOpenSsl = false; } elseif (!function_exists('openssl_random_pseudo_bytes')) { if (null !== $this->logger) { $this->logger->notice('It is recommended that you enable the "openssl" extension for random number generation.'); } $this->useOpenSsl = false; } else { $this->useOpenSsl = true; } } /** * {@inheritdoc} */ public function nextBytes($nbBytes) { // try OpenSSL if ($this->useOpenSsl) { $bytes = openssl_random_pseudo_bytes($nbBytes, $strong); if (false !== $bytes && true === $strong) { return $bytes; } if (null !== $this->logger) { $this->logger->info('OpenSSL did not produce a secure random number.'); } } // initialize seed if (null === $this->seed) { if (null === $this->seedFile) { throw new \RuntimeException('You need to specify a file path to store the seed.'); } if (is_file($this->seedFile)) { list($this->seed, $this->seedLastUpdatedAt) = $this->readSeed(); } else { $this->seed = uniqid(mt_rand(), true); $this->updateSeed(); } } $bytes = ''; while (strlen($bytes) < $nbBytes) { static $incr = 1; $bytes .= hash('sha512', $incr++.$this->seed.uniqid(mt_rand(), true).$nbBytes, true); $this->seed = base64_encode(hash('sha512', $this->seed.$bytes.$nbBytes, true)); $this->updateSeed(); } return substr($bytes, 0, $nbBytes); } private function readSeed() { return json_decode(file_get_contents($this->seedFile)); } private function updateSeed() { if (!$this->seedUpdated && $this->seedLastUpdatedAt < time() - mt_rand(1, 10)) { file_put_contents($this->seedFile, json_encode(array($this->seed, microtime(true)))); } $this->seedUpdated = true; } } PK]l&Security/Core/AuthenticationEvents.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core; final class AuthenticationEvents { /** * The AUTHENTICATION_SUCCESS event occurs after a user is authenticated * by one provider. * * The event listener method receives a * Symfony\Component\Security\Core\Event\AuthenticationEvent instance. * * @var string */ const AUTHENTICATION_SUCCESS = 'security.authentication.success'; /** * The AUTHENTICATION_FAILURE event occurs after a user cannot be * authenticated by any of the providers. * * The event listener method receives a * Symfony\Component\Security\Core\Event\AuthenticationFailureEvent * instance. * * @var string */ const AUTHENTICATION_FAILURE = 'security.authentication.failure'; } PK]Eh2Security/Core/Event/AuthenticationFailureEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Event; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * This event is dispatched on authentication failure. * * @author Johannes M. Schmitt */ class AuthenticationFailureEvent extends AuthenticationEvent { private $authenticationException; public function __construct(TokenInterface $token, AuthenticationException $ex) { parent::__construct($token); $this->authenticationException = $ex; } public function getAuthenticationException() { return $this->authenticationException; } } PK]+\ //+Security/Core/Event/AuthenticationEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Event; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\EventDispatcher\Event; /** * This is a general purpose authentication event. * * @author Johannes M. Schmitt */ class AuthenticationEvent extends Event { private $authenticationToken; public function __construct(TokenInterface $token) { $this->authenticationToken = $token; } public function getAuthenticationToken() { return $this->authenticationToken; } } PK]bM<<4Security/Core/Exception/UnsupportedUserException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * This exception is thrown when an account is reloaded from a provider which * doesn't support the passed implementation of UserInterface. * * @author Johannes M. Schmitt */ class UnsupportedUserException extends AuthenticationServiceException { } PK]#q44?Security/Core/Exception/InsufficientAuthenticationException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * InsufficientAuthenticationException is thrown if the user credentials are not sufficiently trusted. * * This is the case when a user is anonymous and the resource to be displayed has an access role. * * @author Fabien Potencier * @author Alexander */ class InsufficientAuthenticationException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Not privileged to request the resource.'; } } PK]A.Security/Core/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * Base ExceptionInterface for the Security component. * * @author Bernhard Schussek */ interface ExceptionInterface { } PK] ,Security/Core/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * Base RuntimeException for the Security component. * * @author Bernhard Schussek */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK]O5Security/Core/Exception/InvalidCsrfTokenException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * This exception is thrown when the csrf token is invalid. * * @author Johannes M. Schmitt * @author Alexander */ class InvalidCsrfTokenException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Invalid CSRF token.'; } } PK]:AA2Security/Core/Exception/AccountStatusException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; use Symfony\Component\Security\Core\User\UserInterface; /** * AccountStatusException is the base class for authentication exceptions * caused by the user account status. * * @author Fabien Potencier * @author Alexander */ abstract class AccountStatusException extends AuthenticationException { private $user; /** * Get the user. * * @return UserInterface */ public function getUser() { return $this->user; } /** * Set the user. * * @param UserInterface $user */ public function setUser(UserInterface $user) { $this->user = $user; } /** * {@inheritDoc} */ public function serialize() { return serialize(array( $this->user, parent::serialize(), )); } /** * {@inheritDoc} */ public function unserialize($str) { list($this->user, $parentData) = unserialize($str); parent::unserialize($parentData); } } PK]qUSą1Security/Core/Exception/AccessDeniedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * AccessDeniedException is thrown when the account has not the required role. * * @author Fabien Potencier */ class AccessDeniedException extends \RuntimeException { public function __construct($message = 'Access Denied', \Exception $previous = null) { parent::__construct($message, 403, $previous); } } PK]Xss+Security/Core/Exception/LogoutException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * LogoutException is thrown when the account cannot be logged out. * * @author Jeremy Mikola */ class LogoutException extends \RuntimeException { public function __construct($message = 'Logout Exception', \Exception $previous = null) { parent::__construct($message, 403, $previous); } } PK]e1Security/Core/Exception/NonceExpiredException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * NonceExpiredException is thrown when an authentication is rejected because * the digest nonce has expired. * * @author Fabien Potencier * @author Alexander */ class NonceExpiredException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Digest nonce has expired.'; } } PK]D92Security/Core/Exception/TokenNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * TokenNotFoundException is thrown if a Token cannot be found. * * @author Johannes M. Schmitt * @author Alexander */ class TokenNotFoundException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'No token could be found.'; } } PK]z&7Security/Core/Exception/CredentialsExpiredException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * CredentialsExpiredException is thrown when the user account credentials have expired. * * @author Fabien Potencier * @author Alexander */ class CredentialsExpiredException extends AccountStatusException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Credentials have expired.'; } } PK]zz+Security/Core/Exception/LockedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * LockedException is thrown if the user account is locked. * * @author Fabien Potencier * @author Alexander */ class LockedException extends AccountStatusException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Account is locked.'; } } PK]Ε3Security/Core/Exception/BadCredentialsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * BadCredentialsException is thrown when the user credentials are invalid. * * @author Fabien Potencier * @author Alexander */ class BadCredentialsException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Invalid credentials.'; } } PK]7w-:Security/Core/Exception/AuthenticationServiceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * AuthenticationServiceException is thrown when an authentication request could not be processed due to a system problem. * * @author Fabien Potencier * @author Alexander */ class AuthenticationServiceException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Authentication request could not be processed due to a system problem.'; } } PK]'3Security/Core/Exception/AuthenticationException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * AuthenticationException is the base class for all authentication exceptions. * * @author Fabien Potencier * @author Alexander */ class AuthenticationException extends \RuntimeException implements \Serializable { private $token; /** * Get the token. * * @return TokenInterface */ public function getToken() { return $this->token; } /** * Set the token. * * @param TokenInterface $token */ public function setToken(TokenInterface $token) { $this->token = $token; } public function serialize() { return serialize(array( $this->token, $this->code, $this->message, $this->file, $this->line, )); } public function unserialize($str) { list( $this->token, $this->code, $this->message, $this->file, $this->line ) = unserialize($str); } /** * Message key to be used by the translation component. * * @return string */ public function getMessageKey() { return 'An authentication exception occurred.'; } /** * Message data to be used by the translation component. * * @return array */ public function getMessageData() { return array(); } } PK]@ 5Security/Core/Exception/ProviderNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * ProviderNotFoundException is thrown when no AuthenticationProviderInterface instance * supports an authentication Token. * * @author Fabien Potencier * @author Alexander */ class ProviderNotFoundException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'No authentication provider found to support the authentication token.'; } } PK]և-Security/Core/Exception/DisabledException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * DisabledException is thrown when the user account is disabled. * * @author Fabien Potencier * @author Alexander */ class DisabledException extends AccountStatusException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Account is disabled.'; } } PK]xB3Security/Core/Exception/AccountExpiredException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * AccountExpiredException is thrown when the user account has expired. * * @author Fabien Potencier * @author Alexander */ class AccountExpiredException extends AccountStatusException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Account has expired.'; } } PK]hc0Security/Core/Exception/CookieTheftException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * This exception is thrown when the RememberMeServices implementation * detects that a presented cookie has already been used by someone else. * * @author Johannes M. Schmitt * @author Alexander */ class CookieTheftException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Cookie has already been used by someone else.'; } } PK]ĸFSecurity/Core/Exception/AuthenticationCredentialsNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * AuthenticationCredentialsNotFoundException is thrown when an authentication is rejected * because no Token is available. * * @author Fabien Potencier * @author Alexander */ class AuthenticationCredentialsNotFoundException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Authentication credentials could not be found.'; } } PK]ʝ94Security/Core/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * Base InvalidArgumentException for the Security component. * * @author Bernhard Schussek */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PK] 04}}5Security/Core/Exception/UsernameNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * UsernameNotFoundException is thrown if a User cannot be found by its username. * * @author Fabien Potencier * @author Alexander */ class UsernameNotFoundException extends AuthenticationException { private $username; /** * {@inheritDoc} */ public function getMessageKey() { return 'Username could not be found.'; } /** * Get the username. * * @return string */ public function getUsername() { return $this->username; } /** * Set the username. * * @param string $username */ public function setUsername($username) { $this->username = $username; } /** * {@inheritDoc} */ public function serialize() { return serialize(array( $this->username, parent::serialize(), )); } /** * {@inheritDoc} */ public function unserialize($str) { list($this->username, $parentData) = unserialize($str); parent::unserialize($parentData); } } PK]5]7Security/Core/Exception/SessionUnavailableException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * This exception is thrown when no session is available. * * Possible reasons for this are: * * a) The session timed out because the user waited too long. * b) The user has disabled cookies, and a new session is started on each * request. * * @author Johannes M. Schmitt * @author Alexander */ class SessionUnavailableException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'No session available, it either timed out or cookies are not enabled.'; } } PK]ZvmASecurity/Core/Authentication/RememberMe/InMemoryTokenProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\RememberMe; use Symfony\Component\Security\Core\Exception\TokenNotFoundException; /** * This class is used for testing purposes, and is not really suited for production. * * @author Johannes M. Schmitt */ class InMemoryTokenProvider implements TokenProviderInterface { private $tokens = array(); /** * {@inheritdoc} */ public function loadTokenBySeries($series) { if (!isset($this->tokens[$series])) { throw new TokenNotFoundException('No token found.'); } return $this->tokens[$series]; } /** * {@inheritdoc} */ public function updateToken($series, $tokenValue, \DateTime $lastUsed) { if (!isset($this->tokens[$series])) { throw new TokenNotFoundException('No token found.'); } $token = new PersistentToken( $this->tokens[$series]->getClass(), $this->tokens[$series]->getUsername(), $series, $tokenValue, $lastUsed ); $this->tokens[$series] = $token; } /** * {@inheritdoc} */ public function deleteTokenBySeries($series) { unset($this->tokens[$series]); } /** * {@inheritdoc} */ public function createNewToken(PersistentTokenInterface $token) { $this->tokens[$token->getSeries()] = $token; } } PK]QZZDSecurity/Core/Authentication/RememberMe/PersistentTokenInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\RememberMe; /** * Interface to be implemented by persistent token classes (such as * Doctrine entities representing a remember-me token) * * @author Johannes M. Schmitt */ interface PersistentTokenInterface { /** * Returns the class of the user. * * @return string */ public function getClass(); /** * Returns the username. * * @return string */ public function getUsername(); /** * Returns the series. * * @return string */ public function getSeries(); /** * Returns the token value. * * @return string */ public function getTokenValue(); /** * Returns the time the token was last used. * * @return \DateTime */ public function getLastUsed(); } PK] TO;Security/Core/Authentication/RememberMe/PersistentToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\RememberMe; /** * This class is only used by PersistentTokenRememberMeServices internally. * * @author Johannes M. Schmitt */ final class PersistentToken implements PersistentTokenInterface { private $class; private $username; private $series; private $tokenValue; private $lastUsed; /** * Constructor * * @param string $class * @param string $username * @param string $series * @param string $tokenValue * @param \DateTime $lastUsed * * @throws \InvalidArgumentException */ public function __construct($class, $username, $series, $tokenValue, \DateTime $lastUsed) { if (empty($class)) { throw new \InvalidArgumentException('$class must not be empty.'); } if (empty($username)) { throw new \InvalidArgumentException('$username must not be empty.'); } if (empty($series)) { throw new \InvalidArgumentException('$series must not be empty.'); } if (empty($tokenValue)) { throw new \InvalidArgumentException('$tokenValue must not be empty.'); } $this->class = $class; $this->username = $username; $this->series = $series; $this->tokenValue = $tokenValue; $this->lastUsed = $lastUsed; } /** * {@inheritdoc} */ public function getClass() { return $this->class; } /** * {@inheritdoc} */ public function getUsername() { return $this->username; } /** * {@inheritdoc} */ public function getSeries() { return $this->series; } /** * {@inheritdoc} */ public function getTokenValue() { return $this->tokenValue; } /** * {@inheritdoc} */ public function getLastUsed() { return $this->lastUsed; } } PK] CfBSecurity/Core/Authentication/RememberMe/TokenProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\RememberMe; use Symfony\Component\Security\Core\Exception\TokenNotFoundException; /** * Interface for TokenProviders * * @author Johannes M. Schmitt */ interface TokenProviderInterface { /** * Loads the active token for the given series. * * @param string $series * * @return PersistentTokenInterface * * @throws TokenNotFoundException if the token is not found */ public function loadTokenBySeries($series); /** * Deletes all tokens belonging to series. * * @param string $series */ public function deleteTokenBySeries($series); /** * Updates the token according to this data. * * @param string $series * @param string $tokenValue * @param \DateTime $lastUsed * @throws TokenNotFoundException if the token is not found */ public function updateToken($series, $tokenValue, \DateTime $lastUsed); /** * Creates a new token. * * @param PersistentTokenInterface $token */ public function createNewToken(PersistentTokenInterface $token); } PK]JAJSecurity/Core/Authentication/Provider/RememberMeAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; use Symfony\Component\Security\Core\Exception\BadCredentialsException; class RememberMeAuthenticationProvider implements AuthenticationProviderInterface { private $userChecker; private $key; private $providerKey; /** * Constructor. * * @param UserCheckerInterface $userChecker An UserCheckerInterface interface * @param string $key A key * @param string $providerKey A provider key */ public function __construct(UserCheckerInterface $userChecker, $key, $providerKey) { $this->userChecker = $userChecker; $this->key = $key; $this->providerKey = $providerKey; } /** * {@inheritdoc} */ public function authenticate(TokenInterface $token) { if (!$this->supports($token)) { return; } if ($this->key !== $token->getKey()) { throw new BadCredentialsException('The presented key does not match.'); } $user = $token->getUser(); $this->userChecker->checkPostAuth($user); $authenticatedToken = new RememberMeToken($user, $this->providerKey, $this->key); $authenticatedToken->setAttributes($token->getAttributes()); return $authenticatedToken; } /** * {@inheritdoc} */ public function supports(TokenInterface $token) { return $token instanceof RememberMeToken && $token->getProviderKey() === $this->providerKey; } } PK]a""ISecurity/Core/Authentication/Provider/AuthenticationProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; /** * AuthenticationProviderInterface is the interface for all authentication * providers. * * Concrete implementations processes specific Token instances. * * @author Fabien Potencier */ interface AuthenticationProviderInterface extends AuthenticationManagerInterface { /** * Checks whether this provider supports the given token. * * @param TokenInterface $token A TokenInterface instance * * @return Boolean true if the implementation supports the Token, false otherwise */ public function supports(TokenInterface $token); } PK]CSecurity/Core/Authentication/Provider/DaoAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; /** * DaoAuthenticationProvider uses a UserProviderInterface to retrieve the user * for a UsernamePasswordToken. * * @author Fabien Potencier */ class DaoAuthenticationProvider extends UserAuthenticationProvider { private $encoderFactory; private $userProvider; /** * Constructor. * * @param UserProviderInterface $userProvider An UserProviderInterface instance * @param UserCheckerInterface $userChecker An UserCheckerInterface instance * @param string $providerKey The provider key * @param EncoderFactoryInterface $encoderFactory An EncoderFactoryInterface instance * @param Boolean $hideUserNotFoundExceptions Whether to hide user not found exception or not */ public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey, EncoderFactoryInterface $encoderFactory, $hideUserNotFoundExceptions = true) { parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions); $this->encoderFactory = $encoderFactory; $this->userProvider = $userProvider; } /** * {@inheritdoc} */ protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token) { $currentUser = $token->getUser(); if ($currentUser instanceof UserInterface) { if ($currentUser->getPassword() !== $user->getPassword()) { throw new BadCredentialsException('The credentials were changed from another session.'); } } else { if ("" === ($presentedPassword = $token->getCredentials())) { throw new BadCredentialsException('The presented password cannot be empty.'); } if (!$this->encoderFactory->getEncoder($user)->isPasswordValid($user->getPassword(), $presentedPassword, $user->getSalt())) { throw new BadCredentialsException('The presented password is invalid.'); } } } /** * {@inheritdoc} */ protected function retrieveUser($username, UsernamePasswordToken $token) { $user = $token->getUser(); if ($user instanceof UserInterface) { return $user; } try { $user = $this->userProvider->loadUserByUsername($username); if (!$user instanceof UserInterface) { throw new AuthenticationServiceException('The user provider must return a UserInterface object.'); } return $user; } catch (UsernameNotFoundException $notFound) { $notFound->setUsername($username); throw $notFound; } catch (\Exception $repositoryProblem) { $ex = new AuthenticationServiceException($repositoryProblem->getMessage(), 0, $repositoryProblem); $ex->setToken($token); throw $ex; } } } PK]XISecurity/Core/Authentication/Provider/AnonymousAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; /** * AnonymousAuthenticationProvider validates AnonymousToken instances. * * @author Fabien Potencier */ class AnonymousAuthenticationProvider implements AuthenticationProviderInterface { private $key; /** * Constructor. * * @param string $key The key shared with the authentication token */ public function __construct($key) { $this->key = $key; } /** * {@inheritdoc} */ public function authenticate(TokenInterface $token) { if (!$this->supports($token)) { return null; } if ($this->key !== $token->getKey()) { throw new BadCredentialsException('The Token does not contain the expected key.'); } return $token; } /** * {@inheritdoc} */ public function supports(TokenInterface $token) { return $token instanceof AnonymousToken; } } PK]>,vvFSecurity/Core/Authentication/Provider/SimpleAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; /** * @author Jordi Boggiano */ class SimpleAuthenticationProvider implements AuthenticationProviderInterface { private $simpleAuthenticator; private $userProvider; private $providerKey; public function __construct(SimpleAuthenticatorInterface $simpleAuthenticator, UserProviderInterface $userProvider, $providerKey) { $this->simpleAuthenticator = $simpleAuthenticator; $this->userProvider = $userProvider; $this->providerKey = $providerKey; } public function authenticate(TokenInterface $token) { $authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey); if ($authToken instanceof TokenInterface) { return $authToken; } throw new AuthenticationException('Simple authenticator failed to return an authenticated token.'); } public function supports(TokenInterface $token) { return $this->simpleAuthenticator->supportsToken($token, $this->providerKey); } } PK]un\ PSecurity/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * Processes a pre-authenticated authentication request. * * This authentication provider will not perform any checks on authentication * requests, as they should already be pre-authenticated. However, the * UserProviderInterface implementation may still throw a * UsernameNotFoundException, for example. * * @author Fabien Potencier */ class PreAuthenticatedAuthenticationProvider implements AuthenticationProviderInterface { private $userProvider; private $userChecker; private $providerKey; /** * Constructor. * * @param UserProviderInterface $userProvider An UserProviderInterface instance * @param UserCheckerInterface $userChecker An UserCheckerInterface instance * @param string $providerKey The provider key */ public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey) { $this->userProvider = $userProvider; $this->userChecker = $userChecker; $this->providerKey = $providerKey; } /** * {@inheritdoc} */ public function authenticate(TokenInterface $token) { if (!$this->supports($token)) { return null; } if (!$user = $token->getUser()) { throw new BadCredentialsException('No pre-authenticated principal found in request.'); } /* if (null === $token->getCredentials()) { throw new BadCredentialsException('No pre-authenticated credentials found in request.'); } */ $user = $this->userProvider->loadUserByUsername($user); $this->userChecker->checkPostAuth($user); $authenticatedToken = new PreAuthenticatedToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles()); $authenticatedToken->setAttributes($token->getAttributes()); return $authenticatedToken; } /** * {@inheritdoc} */ public function supports(TokenInterface $token) { return $token instanceof PreAuthenticatedToken && $this->providerKey === $token->getProviderKey(); } } PK]byyDSecurity/Core/Authentication/Provider/UserAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Role\SwitchUserRole; /** * UserProviderInterface retrieves users for UsernamePasswordToken tokens. * * @author Fabien Potencier */ abstract class UserAuthenticationProvider implements AuthenticationProviderInterface { private $hideUserNotFoundExceptions; private $userChecker; private $providerKey; /** * Constructor. * * @param UserCheckerInterface $userChecker An UserCheckerInterface interface * @param string $providerKey A provider key * @param Boolean $hideUserNotFoundExceptions Whether to hide user not found exception or not * * @throws \InvalidArgumentException */ public function __construct(UserCheckerInterface $userChecker, $providerKey, $hideUserNotFoundExceptions = true) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->userChecker = $userChecker; $this->providerKey = $providerKey; $this->hideUserNotFoundExceptions = $hideUserNotFoundExceptions; } /** * {@inheritdoc} */ public function authenticate(TokenInterface $token) { if (!$this->supports($token)) { return null; } $username = $token->getUsername(); if (empty($username)) { $username = 'NONE_PROVIDED'; } try { $user = $this->retrieveUser($username, $token); } catch (UsernameNotFoundException $notFound) { if ($this->hideUserNotFoundExceptions) { throw new BadCredentialsException('Bad credentials', 0, $notFound); } $notFound->setUsername($username); throw $notFound; } if (!$user instanceof UserInterface) { throw new AuthenticationServiceException('retrieveUser() must return a UserInterface.'); } try { $this->userChecker->checkPreAuth($user); $this->checkAuthentication($user, $token); $this->userChecker->checkPostAuth($user); } catch (BadCredentialsException $e) { if ($this->hideUserNotFoundExceptions) { throw new BadCredentialsException('Bad credentials', 0, $e); } throw $e; } $authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $this->getRoles($user, $token)); $authenticatedToken->setAttributes($token->getAttributes()); return $authenticatedToken; } /** * {@inheritdoc} */ public function supports(TokenInterface $token) { return $token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey(); } /** * Retrieves roles from user and appends SwitchUserRole if original token contained one. * * @param UserInterface $user The user * @param TokenInterface $token The token * * @return Role[] The user roles */ private function getRoles(UserInterface $user, TokenInterface $token) { $roles = $user->getRoles(); foreach ($token->getRoles() as $role) { if ($role instanceof SwitchUserRole) { $roles[] = $role; break; } } return $roles; } /** * Retrieves the user from an implementation-specific location. * * @param string $username The username to retrieve * @param UsernamePasswordToken $token The Token * * @return UserInterface The user * * @throws AuthenticationException if the credentials could not be validated */ abstract protected function retrieveUser($username, UsernamePasswordToken $token); /** * Does additional checks on the user and token (like validating the * credentials). * * @param UserInterface $user The retrieved UserInterface instance * @param UsernamePasswordToken $token The UsernamePasswordToken token to be authenticated * * @throws AuthenticationException if the credentials could not be validated */ abstract protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token); } PK]r3WWESecurity/Core/Authentication/AuthenticationTrustResolverInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * Interface for resolving the authentication status of a given token. * * @author Johannes M. Schmitt */ interface AuthenticationTrustResolverInterface { /** * Resolves whether the passed token implementation is authenticated * anonymously. * * If null is passed, the method must return false. * * @param TokenInterface $token * * @return Boolean */ public function isAnonymous(TokenInterface $token = null); /** * Resolves whether the passed token implementation is authenticated * using remember-me capabilities. * * @param TokenInterface $token * * @return Boolean */ public function isRememberMe(TokenInterface $token = null); /** * Resolves whether the passed token implementation is fully authenticated. * * @param TokenInterface $token * * @return Boolean */ public function isFullFledged(TokenInterface $token = null); } PK]¬> ##@Security/Core/Authentication/SimplePreAuthenticatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\HttpFoundation\Request; /** * @author Jordi Boggiano */ interface SimplePreAuthenticatorInterface extends SimpleAuthenticatorInterface { public function createToken(Request $request, $providerKey); } PK]W=Security/Core/Authentication/SimpleAuthenticatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; /** * @author Jordi Boggiano */ interface SimpleAuthenticatorInterface { public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey); public function supportsToken(TokenInterface $token, $providerKey); } PK]f ?Security/Core/Authentication/AuthenticationManagerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; /** * AuthenticationManagerInterface is the interface for authentication managers, * which process Token authentication. * * @author Fabien Potencier */ interface AuthenticationManagerInterface { /** * Attempts to authenticate a TokenInterface object. * * @param TokenInterface $token The TokenInterface instance to authenticate * * @return TokenInterface An authenticated TokenInterface instance, never null * * @throws AuthenticationException if the authentication fails */ public function authenticate(TokenInterface $token); } PK]6` ` <Security/Core/Authentication/Token/UsernamePasswordToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; use Symfony\Component\Security\Core\Role\RoleInterface; /** * UsernamePasswordToken implements a username and password token. * * @author Fabien Potencier */ class UsernamePasswordToken extends AbstractToken { private $credentials; private $providerKey; /** * Constructor. * * @param string $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method. * @param string $credentials This usually is the password of the user * @param string $providerKey The provider key * @param RoleInterface[] $roles An array of roles * * @throws \InvalidArgumentException */ public function __construct($user, $credentials, $providerKey, array $roles = array()) { parent::__construct($roles); if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->setUser($user); $this->credentials = $credentials; $this->providerKey = $providerKey; parent::setAuthenticated(count($roles) > 0); } /** * {@inheritdoc} */ public function setAuthenticated($isAuthenticated) { if ($isAuthenticated) { throw new \LogicException('Cannot set this token to trusted after instantiation.'); } parent::setAuthenticated(false); } /** * {@inheritdoc} */ public function getCredentials() { return $this->credentials; } /** * Returns the provider key. * * @return string The provider key */ public function getProviderKey() { return $this->providerKey; } /** * {@inheritdoc} */ public function eraseCredentials() { parent::eraseCredentials(); $this->credentials = null; } /** * {@inheritdoc} */ public function serialize() { return serialize(array($this->credentials, $this->providerKey, parent::serialize())); } /** * {@inheritdoc} */ public function unserialize($serialized) { list($this->credentials, $this->providerKey, $parentStr) = unserialize($serialized); parent::unserialize($parentStr); } } PK]w 6Security/Core/Authentication/Token/RememberMeToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; use Symfony\Component\Security\Core\User\UserInterface; /** * Authentication Token for "Remember-Me". * * @author Johannes M. Schmitt */ class RememberMeToken extends AbstractToken { private $key; private $providerKey; /** * Constructor. * * @param UserInterface $user * @param string $providerKey * @param string $key * * @throws \InvalidArgumentException */ public function __construct(UserInterface $user, $providerKey, $key) { parent::__construct($user->getRoles()); if (empty($key)) { throw new \InvalidArgumentException('$key must not be empty.'); } if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->providerKey = $providerKey; $this->key = $key; $this->setUser($user); parent::setAuthenticated(true); } /** * {@inheritdoc} */ public function setAuthenticated($authenticated) { if ($authenticated) { throw new \LogicException('You cannot set this token to authenticated after creation.'); } parent::setAuthenticated(false); } /** * Returns the provider key. * * @return string The provider key */ public function getProviderKey() { return $this->providerKey; } /** * Returns the key. * * @return string The Key */ public function getKey() { return $this->key; } /** * {@inheritdoc} */ public function getCredentials() { return ''; } /** * {@inheritdoc} */ public function serialize() { return serialize(array( $this->key, $this->providerKey, parent::serialize(), )); } /** * {@inheritdoc} */ public function unserialize($serialized) { list($this->key, $this->providerKey, $parentStr) = unserialize($serialized); parent::unserialize($parentStr); } } PK]{Z--5Security/Core/Authentication/Token/AnonymousToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; use Symfony\Component\Security\Core\Role\RoleInterface; /** * AnonymousToken represents an anonymous token. * * @author Fabien Potencier */ class AnonymousToken extends AbstractToken { private $key; /** * Constructor. * * @param string $key The key shared with the authentication provider * @param string $user The user * @param RoleInterface[] $roles An array of roles */ public function __construct($key, $user, array $roles = array()) { parent::__construct($roles); $this->key = $key; $this->setUser($user); $this->setAuthenticated(true); } /** * {@inheritdoc} */ public function getCredentials() { return ''; } /** * Returns the key. * * @return string The Key */ public function getKey() { return $this->key; } /** * {@inheritDoc} */ public function serialize() { return serialize(array($this->key, parent::serialize())); } /** * {@inheritDoc} */ public function unserialize($serialized) { list($this->key, $parentStr) = unserialize($serialized); parent::unserialize($parentStr); } } PK]γ__<Security/Core/Authentication/Token/PreAuthenticatedToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; /** * PreAuthenticatedToken implements a pre-authenticated token. * * @author Fabien Potencier */ class PreAuthenticatedToken extends AbstractToken { private $credentials; private $providerKey; /** * Constructor. */ public function __construct($user, $credentials, $providerKey, array $roles = array()) { parent::__construct($roles); if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->setUser($user); $this->credentials = $credentials; $this->providerKey = $providerKey; if ($roles) { $this->setAuthenticated(true); } } /** * Returns the provider key. * * @return string The provider key */ public function getProviderKey() { return $this->providerKey; } /** * {@inheritdoc} */ public function getCredentials() { return $this->credentials; } /** * {@inheritdoc} */ public function eraseCredentials() { parent::eraseCredentials(); $this->credentials = null; } /** * {@inheritdoc} */ public function serialize() { return serialize(array($this->credentials, $this->providerKey, parent::serialize())); } /** * {@inheritdoc} */ public function unserialize($str) { list($this->credentials, $this->providerKey, $parentStr) = unserialize($str); parent::unserialize($parentStr); } } PK]tC 5Security/Core/Authentication/Token/TokenInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; use Symfony\Component\Security\Core\Role\RoleInterface; /** * TokenInterface is the interface for the user authentication information. * * @author Fabien Potencier * @author Johannes M. Schmitt */ interface TokenInterface extends \Serializable { /** * Returns a string representation of the Token. * * This is only to be used for debugging purposes. * * @return string */ public function __toString(); /** * Returns the user roles. * * @return RoleInterface[] An array of RoleInterface instances. */ public function getRoles(); /** * Returns the user credentials. * * @return mixed The user credentials */ public function getCredentials(); /** * Returns a user representation. * * @return mixed either returns an object which implements __toString(), or * a primitive string is returned. */ public function getUser(); /** * Sets a user. * * @param mixed $user */ public function setUser($user); /** * Returns the username. * * @return string */ public function getUsername(); /** * Returns whether the user is authenticated or not. * * @return Boolean true if the token has been authenticated, false otherwise */ public function isAuthenticated(); /** * Sets the authenticated flag. * * @param Boolean $isAuthenticated The authenticated flag */ public function setAuthenticated($isAuthenticated); /** * Removes sensitive information from the token. */ public function eraseCredentials(); /** * Returns the token attributes. * * @return array The token attributes */ public function getAttributes(); /** * Sets the token attributes. * * @param array $attributes The token attributes */ public function setAttributes(array $attributes); /** * Returns true if the attribute exists. * * @param string $name The attribute name * * @return Boolean true if the attribute exists, false otherwise */ public function hasAttribute($name); /** * Returns an attribute value. * * @param string $name The attribute name * * @return mixed The attribute value * * @throws \InvalidArgumentException When attribute doesn't exist for this token */ public function getAttribute($name); /** * Sets an attribute. * * @param string $name The attribute name * @param mixed $value The attribute value */ public function setAttribute($name, $value); } PK]44Security/Core/Authentication/Token/AbstractToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; use Symfony\Component\Security\Core\Role\RoleInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\AdvancedUserInterface; use Symfony\Component\Security\Core\User\EquatableInterface; /** * Base class for Token instances. * * @author Fabien Potencier * @author Johannes M. Schmitt */ abstract class AbstractToken implements TokenInterface { private $user; private $roles = array(); private $authenticated = false; private $attributes = array(); /** * Constructor. * * @param RoleInterface[] $roles An array of roles * * @throws \InvalidArgumentException */ public function __construct(array $roles = array()) { foreach ($roles as $role) { if (is_string($role)) { $role = new Role($role); } elseif (!$role instanceof RoleInterface) { throw new \InvalidArgumentException(sprintf('$roles must be an array of strings, or RoleInterface instances, but got %s.', gettype($role))); } $this->roles[] = $role; } } /** * {@inheritdoc} */ public function getRoles() { return $this->roles; } /** * {@inheritdoc} */ public function getUsername() { if ($this->user instanceof UserInterface) { return $this->user->getUsername(); } return (string) $this->user; } /** * {@inheritdoc} */ public function getUser() { return $this->user; } /** * Sets the user in the token. * * The user can be a UserInterface instance, or an object implementing * a __toString method or the username as a regular string. * * @param mixed $user The user * @throws \InvalidArgumentException */ public function setUser($user) { if (!($user instanceof UserInterface || (is_object($user) && method_exists($user, '__toString')) || is_string($user))) { throw new \InvalidArgumentException('$user must be an instanceof UserInterface, an object implementing a __toString method, or a primitive string.'); } if (null === $this->user) { $changed = false; } elseif ($this->user instanceof UserInterface) { if (!$user instanceof UserInterface) { $changed = true; } else { $changed = $this->hasUserChanged($user); } } elseif ($user instanceof UserInterface) { $changed = true; } else { $changed = (string) $this->user !== (string) $user; } if ($changed) { $this->setAuthenticated(false); } $this->user = $user; } /** * {@inheritdoc} */ public function isAuthenticated() { return $this->authenticated; } /** * {@inheritdoc} */ public function setAuthenticated($authenticated) { $this->authenticated = (Boolean) $authenticated; } /** * {@inheritdoc} */ public function eraseCredentials() { if ($this->getUser() instanceof UserInterface) { $this->getUser()->eraseCredentials(); } } /** * {@inheritdoc} */ public function serialize() { return serialize( array( is_object($this->user) ? clone $this->user : $this->user, $this->authenticated, $this->roles, $this->attributes ) ); } /** * {@inheritdoc} */ public function unserialize($serialized) { list($this->user, $this->authenticated, $this->roles, $this->attributes) = unserialize($serialized); } /** * Returns the token attributes. * * @return array The token attributes */ public function getAttributes() { return $this->attributes; } /** * Sets the token attributes. * * @param array $attributes The token attributes */ public function setAttributes(array $attributes) { $this->attributes = $attributes; } /** * Returns true if the attribute exists. * * @param string $name The attribute name * * @return Boolean true if the attribute exists, false otherwise */ public function hasAttribute($name) { return array_key_exists($name, $this->attributes); } /** * Returns an attribute value. * * @param string $name The attribute name * * @return mixed The attribute value * * @throws \InvalidArgumentException When attribute doesn't exist for this token */ public function getAttribute($name) { if (!array_key_exists($name, $this->attributes)) { throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name)); } return $this->attributes[$name]; } /** * Sets an attribute. * * @param string $name The attribute name * @param mixed $value The attribute value */ public function setAttribute($name, $value) { $this->attributes[$name] = $value; } /** * {@inheritDoc} */ public function __toString() { $class = get_class($this); $class = substr($class, strrpos($class, '\\')+1); $roles = array(); foreach ($this->roles as $role) { $roles[] = $role->getRole(); } return sprintf('%s(user="%s", authenticated=%s, roles="%s")', $class, $this->getUsername(), json_encode($this->authenticated), implode(', ', $roles)); } private function hasUserChanged(UserInterface $user) { if (!($this->user instanceof UserInterface)) { throw new \BadMethodCallException('Method "hasUserChanged" should be called when current user class is instance of "UserInterface".'); } if ($this->user instanceof EquatableInterface) { return ! (Boolean) $this->user->isEqualTo($user); } if ($this->user->getPassword() !== $user->getPassword()) { return true; } if ($this->user->getSalt() !== $user->getSalt()) { return true; } if ($this->user->getUsername() !== $user->getUsername()) { return true; } if ($this->user instanceof AdvancedUserInterface && $user instanceof AdvancedUserInterface) { if ($this->user->isAccountNonExpired() !== $user->isAccountNonExpired()) { return true; } if ($this->user->isAccountNonLocked() !== $user->isAccountNonLocked()) { return true; } if ($this->user->isCredentialsNonExpired() !== $user->isCredentialsNonExpired()) { return true; } if ($this->user->isEnabled() !== $user->isEnabled()) { return true; } } elseif ($this->user instanceof AdvancedUserInterface xor $user instanceof AdvancedUserInterface) { return true; } return false; } } PK]x$cc>Security/Core/Authentication/AuthenticationProviderManager.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent; use Symfony\Component\Security\Core\Event\AuthenticationEvent; use Symfony\Component\Security\Core\AuthenticationEvents; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Security\Core\Exception\AccountStatusException; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\ProviderNotFoundException; use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * AuthenticationProviderManager uses a list of AuthenticationProviderInterface * instances to authenticate a Token. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class AuthenticationProviderManager implements AuthenticationManagerInterface { private $providers; private $eraseCredentials; private $eventDispatcher; /** * Constructor. * * @param AuthenticationProviderInterface[] $providers An array of AuthenticationProviderInterface instances * @param Boolean $eraseCredentials Whether to erase credentials after authentication or not * * @throws \InvalidArgumentException */ public function __construct(array $providers, $eraseCredentials = true) { if (!$providers) { throw new \InvalidArgumentException('You must at least add one authentication provider.'); } $this->providers = $providers; $this->eraseCredentials = (Boolean) $eraseCredentials; } public function setEventDispatcher(EventDispatcherInterface $dispatcher) { $this->eventDispatcher = $dispatcher; } /** * {@inheritdoc} */ public function authenticate(TokenInterface $token) { $lastException = null; $result = null; foreach ($this->providers as $provider) { if (!$provider->supports($token)) { continue; } try { $result = $provider->authenticate($token); if (null !== $result) { break; } } catch (AccountStatusException $e) { $e->setToken($token); throw $e; } catch (AuthenticationException $e) { $lastException = $e; } } if (null !== $result) { if (true === $this->eraseCredentials) { $result->eraseCredentials(); } if (null !== $this->eventDispatcher) { $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_SUCCESS, new AuthenticationEvent($result)); } return $result; } if (null === $lastException) { $lastException = new ProviderNotFoundException(sprintf('No Authentication Provider found for token of class "%s".', get_class($token))); } if (null !== $this->eventDispatcher) { $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_FAILURE, new AuthenticationFailureEvent($token, $lastException)); } $lastException->setToken($token); throw $lastException; } } PK]J-W;::ASecurity/Core/Authentication/SimpleFormAuthenticatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\HttpFoundation\Request; /** * @author Jordi Boggiano */ interface SimpleFormAuthenticatorInterface extends SimpleAuthenticatorInterface { public function createToken(Request $request, $username, $password, $providerKey); } PK]:6<Security/Core/Authentication/AuthenticationTrustResolver.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * The default implementation of the authentication trust resolver. * * @author Johannes M. Schmitt */ class AuthenticationTrustResolver implements AuthenticationTrustResolverInterface { private $anonymousClass; private $rememberMeClass; /** * Constructor * * @param string $anonymousClass * @param string $rememberMeClass */ public function __construct($anonymousClass, $rememberMeClass) { $this->anonymousClass = $anonymousClass; $this->rememberMeClass = $rememberMeClass; } /** * {@inheritDoc} */ public function isAnonymous(TokenInterface $token = null) { if (null === $token) { return false; } return $token instanceof $this->anonymousClass; } /** * {@inheritDoc} */ public function isRememberMe(TokenInterface $token = null) { if (null === $token) { return false; } return $token instanceof $this->rememberMeClass; } /** * {@inheritDoc} */ public function isFullFledged(TokenInterface $token = null) { if (null === $token) { return false; } return !$this->isAnonymous($token) && !$this->isRememberMe($token); } } PK] 77=Security/Core/Validator/Constraints/UserPasswordValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Validator\Constraints; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; class UserPasswordValidator extends ConstraintValidator { private $securityContext; private $encoderFactory; public function __construct(SecurityContextInterface $securityContext, EncoderFactoryInterface $encoderFactory) { $this->securityContext = $securityContext; $this->encoderFactory = $encoderFactory; } /** * {@inheritdoc} */ public function validate($password, Constraint $constraint) { $user = $this->securityContext->getToken()->getUser(); if (!$user instanceof UserInterface) { throw new ConstraintDefinitionException('The User object must implement the UserInterface interface.'); } $encoder = $this->encoderFactory->getEncoder($user); if (!$encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt())) { $this->context->addViolation($constraint->message); } } } PK]i4Security/Core/Validator/Constraints/UserPassword.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation */ class UserPassword extends Constraint { public $message = 'This value should be the user current password.'; public $service = 'security.validator.user_password'; /** * {@inheritdoc} */ public function validatedBy() { return $this->service; } } PK]'za! ! !Security/Core/SecurityContext.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core; use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * SecurityContext is the main entry point of the Security component. * * It gives access to the token representing the current user authentication. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class SecurityContext implements SecurityContextInterface { private $token; private $accessDecisionManager; private $authenticationManager; private $alwaysAuthenticate; /** * Constructor. * * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManager instance * @param AccessDecisionManagerInterface|null $accessDecisionManager An AccessDecisionManager instance * @param Boolean $alwaysAuthenticate */ public function __construct(AuthenticationManagerInterface $authenticationManager, AccessDecisionManagerInterface $accessDecisionManager, $alwaysAuthenticate = false) { $this->authenticationManager = $authenticationManager; $this->accessDecisionManager = $accessDecisionManager; $this->alwaysAuthenticate = $alwaysAuthenticate; } /** * {@inheritdoc} * * @throws AuthenticationCredentialsNotFoundException when the security context has no authentication token. */ final public function isGranted($attributes, $object = null) { if (null === $this->token) { throw new AuthenticationCredentialsNotFoundException('The security context contains no authentication token. One possible reason may be that there is no firewall configured for this URL.'); } if ($this->alwaysAuthenticate || !$this->token->isAuthenticated()) { $this->token = $this->authenticationManager->authenticate($this->token); } if (!is_array($attributes)) { $attributes = array($attributes); } return $this->accessDecisionManager->decide($this->token, $attributes, $object); } /** * {@inheritdoc} */ public function getToken() { return $this->token; } /** * {@inheritdoc} */ public function setToken(TokenInterface $token = null) { $this->token = $token; } } PK]!@  /Security/Core/Encoder/Pbkdf2PasswordEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\Exception\BadCredentialsException; /** * Pbkdf2PasswordEncoder uses the PBKDF2 (Password-Based Key Derivation Function 2). * * Providing a high level of Cryptographic security, * PBKDF2 is recommended by the National Institute of Standards and Technology (NIST). * * But also warrants a warning, using PBKDF2 (with a high number of iterations) slows down the process. * PBKDF2 should be used with caution and care. * * @author Sebastiaan Stok * @author Andrew Johnson * @author Fabien Potencier */ class Pbkdf2PasswordEncoder extends BasePasswordEncoder { private $algorithm; private $encodeHashAsBase64; private $iterations; private $length; /** * Constructor. * * @param string $algorithm The digest algorithm to use * @param Boolean $encodeHashAsBase64 Whether to base64 encode the password hash * @param integer $iterations The number of iterations to use to stretch the password hash * @param integer $length Length of derived key to create */ public function __construct($algorithm = 'sha512', $encodeHashAsBase64 = true, $iterations = 1000, $length = 40) { $this->algorithm = $algorithm; $this->encodeHashAsBase64 = $encodeHashAsBase64; $this->iterations = $iterations; $this->length = $length; } /** * {@inheritdoc} * * @throws \LogicException when the algorithm is not supported */ public function encodePassword($raw, $salt) { if ($this->isPasswordTooLong($raw)) { throw new BadCredentialsException('Invalid password.'); } if (!in_array($this->algorithm, hash_algos(), true)) { throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm)); } if (function_exists('hash_pbkdf2')) { $digest = hash_pbkdf2($this->algorithm, $raw, $salt, $this->iterations, $this->length, true); } else { $digest = $this->hashPbkdf2($this->algorithm, $raw, $salt, $this->iterations, $this->length); } return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest); } /** * {@inheritdoc} */ public function isPasswordValid($encoded, $raw, $salt) { return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt)); } private function hashPbkdf2($algorithm, $password, $salt, $iterations, $length = 0) { // Number of blocks needed to create the derived key $blocks = ceil($length / strlen(hash($algorithm, null, true))); $digest = ''; for ($i = 1; $i <= $blocks; $i++) { $ib = $block = hash_hmac($algorithm, $salt.pack('N', $i), $password, true); // Iterations for ($j = 1; $j < $iterations; $j++) { $ib ^= ($block = hash_hmac($algorithm, $block, $password, true)); } $digest .= $ib; } return substr($digest, 0, $this->length); } } PK]Æ /Security/Core/Encoder/BCryptPasswordEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\Exception\BadCredentialsException; /** * @author Elnur Abdurrakhimov * @author Terje Bråten */ class BCryptPasswordEncoder extends BasePasswordEncoder { /** * @var string */ private $cost; /** * Constructor. * * @param integer $cost The algorithmic cost that should be used * * @throws \RuntimeException When no BCrypt encoder is available * @throws \InvalidArgumentException if cost is out of range */ public function __construct($cost) { if (!function_exists('password_hash')) { throw new \RuntimeException('To use the BCrypt encoder, you need to upgrade to PHP 5.5 or install the "ircmaxell/password-compat" via Composer.'); } $cost = (int) $cost; if ($cost < 4 || $cost > 31) { throw new \InvalidArgumentException('Cost must be in the range of 4-31.'); } $this->cost = $cost; } /** * Encodes the raw password. * * It doesn't work with PHP versions lower than 5.3.7, since * the password compat library uses CRYPT_BLOWFISH hash type with * the "$2y$" salt prefix (which is not available in the early PHP versions). * @see https://github.com/ircmaxell/password_compat/issues/10#issuecomment-11203833 * * It is almost best to **not** pass a salt and let PHP generate one for you. * * @param string $raw The password to encode * @param string $salt The salt * * @return string The encoded password * * @link http://lxr.php.net/xref/PHP_5_5/ext/standard/password.c#111 */ public function encodePassword($raw, $salt) { if ($this->isPasswordTooLong($raw)) { throw new BadCredentialsException('Invalid password.'); } $options = array('cost' => $this->cost); if ($salt) { $options['salt'] = $salt; } return password_hash($raw, PASSWORD_BCRYPT, $options); } /** * {@inheritdoc} */ public function isPasswordValid($encoded, $raw, $salt) { return !$this->isPasswordTooLong($raw) && password_verify($raw, $encoded); } } PK]^6Security/Core/Encoder/MessageDigestPasswordEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\Exception\BadCredentialsException; /** * MessageDigestPasswordEncoder uses a message digest algorithm. * * @author Fabien Potencier */ class MessageDigestPasswordEncoder extends BasePasswordEncoder { private $algorithm; private $encodeHashAsBase64; private $iterations; /** * Constructor. * * @param string $algorithm The digest algorithm to use * @param Boolean $encodeHashAsBase64 Whether to base64 encode the password hash * @param integer $iterations The number of iterations to use to stretch the password hash */ public function __construct($algorithm = 'sha512', $encodeHashAsBase64 = true, $iterations = 5000) { $this->algorithm = $algorithm; $this->encodeHashAsBase64 = $encodeHashAsBase64; $this->iterations = $iterations; } /** * {@inheritdoc} */ public function encodePassword($raw, $salt) { if ($this->isPasswordTooLong($raw)) { throw new BadCredentialsException('Invalid password.'); } if (!in_array($this->algorithm, hash_algos(), true)) { throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm)); } $salted = $this->mergePasswordAndSalt($raw, $salt); $digest = hash($this->algorithm, $salted, true); // "stretch" hash for ($i = 1; $i < $this->iterations; $i++) { $digest = hash($this->algorithm, $digest.$salted, true); } return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest); } /** * {@inheritdoc} */ public function isPasswordValid($encoded, $raw, $salt) { return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt)); } } PK];D(Security/Core/Encoder/EncoderFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; /** * A generic encoder factory implementation * * @author Johannes M. Schmitt */ class EncoderFactory implements EncoderFactoryInterface { private $encoders; public function __construct(array $encoders) { $this->encoders = $encoders; } /** * {@inheritDoc} */ public function getEncoder($user) { foreach ($this->encoders as $class => $encoder) { if ((is_object($user) && !$user instanceof $class) || (!is_object($user) && !is_subclass_of($user, $class) && $user != $class)) { continue; } if (!$encoder instanceof PasswordEncoderInterface) { return $this->encoders[$class] = $this->createEncoder($encoder); } return $this->encoders[$class]; } throw new \RuntimeException(sprintf('No encoder has been configured for account "%s".', is_object($user) ? get_class($user) : $user)); } /** * Creates the actual encoder instance * * @param array $config * * @return PasswordEncoderInterface * * @throws \InvalidArgumentException */ private function createEncoder(array $config) { if (!isset($config['class'])) { throw new \InvalidArgumentException(sprintf('"class" must be set in %s.', json_encode($config))); } if (!isset($config['arguments'])) { throw new \InvalidArgumentException(sprintf('"arguments" must be set in %s.', json_encode($config))); } $reflection = new \ReflectionClass($config['class']); return $reflection->newInstanceArgs($config['arguments']); } } PK]#MMqq1Security/Core/Encoder/EncoderFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\User\UserInterface; /** * EncoderFactoryInterface to support different encoders for different accounts. * * @author Johannes M. Schmitt */ interface EncoderFactoryInterface { /** * Returns the password encoder to use for the given account. * * @param UserInterface|string $user A UserInterface instance or a class name * * @return PasswordEncoderInterface * * @throws \RuntimeException when no password encoder could be found for the user */ public function getEncoder($user); } PK],>"2Security/Core/Encoder/PlaintextPasswordEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\Exception\BadCredentialsException; /** * PlaintextPasswordEncoder does not do any encoding. * * @author Fabien Potencier */ class PlaintextPasswordEncoder extends BasePasswordEncoder { private $ignorePasswordCase; /** * Constructor. * * @param Boolean $ignorePasswordCase Compare password case-insensitive */ public function __construct($ignorePasswordCase = false) { $this->ignorePasswordCase = $ignorePasswordCase; } /** * {@inheritdoc} */ public function encodePassword($raw, $salt) { if ($this->isPasswordTooLong($raw)) { throw new BadCredentialsException('Invalid password.'); } return $this->mergePasswordAndSalt($raw, $salt); } /** * {@inheritdoc} */ public function isPasswordValid($encoded, $raw, $salt) { if ($this->isPasswordTooLong($raw)) { return false; } $pass2 = $this->mergePasswordAndSalt($raw, $salt); if (!$this->ignorePasswordCase) { return $this->comparePasswords($encoded, $pass2); } return $this->comparePasswords(strtolower($encoded), strtolower($pass2)); } } PK]7 -Security/Core/Encoder/BasePasswordEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\Util\StringUtils; /** * BasePasswordEncoder is the base class for all password encoders. * * @author Fabien Potencier */ abstract class BasePasswordEncoder implements PasswordEncoderInterface { const MAX_PASSWORD_LENGTH = 4096; /** * Demerges a merge password and salt string. * * @param string $mergedPasswordSalt The merged password and salt string * * @return array An array where the first element is the password and the second the salt */ protected function demergePasswordAndSalt($mergedPasswordSalt) { if (empty($mergedPasswordSalt)) { return array('', ''); } $password = $mergedPasswordSalt; $salt = ''; $saltBegins = strrpos($mergedPasswordSalt, '{'); if (false !== $saltBegins && $saltBegins + 1 < strlen($mergedPasswordSalt)) { $salt = substr($mergedPasswordSalt, $saltBegins + 1, -1); $password = substr($mergedPasswordSalt, 0, $saltBegins); } return array($password, $salt); } /** * Merges a password and a salt. * * @param string $password the password to be used * @param string $salt the salt to be used * * @return string a merged password and salt * * @throws \InvalidArgumentException */ protected function mergePasswordAndSalt($password, $salt) { if (empty($salt)) { return $password; } if (false !== strrpos($salt, '{') || false !== strrpos($salt, '}')) { throw new \InvalidArgumentException('Cannot use { or } in salt.'); } return $password.'{'.$salt.'}'; } /** * Compares two passwords. * * This method implements a constant-time algorithm to compare passwords to * avoid (remote) timing attacks. * * @param string $password1 The first password * @param string $password2 The second password * * @return Boolean true if the two passwords are the same, false otherwise */ protected function comparePasswords($password1, $password2) { return StringUtils::equals($password1, $password2); } /** * Checks if the password is too long. * * @return Boolean true if the password is too long, false otherwise */ protected function isPasswordTooLong($password) { return strlen($password) > self::MAX_PASSWORD_LENGTH; } } PK]E 2Security/Core/Encoder/PasswordEncoderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; /** * PasswordEncoderInterface is the interface for all encoders. * * @author Fabien Potencier */ interface PasswordEncoderInterface { /** * Encodes the raw password. * * @param string $raw The password to encode * @param string $salt The salt * * @return string The encoded password */ public function encodePassword($raw, $salt); /** * Checks a raw password against an encoded password. * * @param string $encoded An encoded password * @param string $raw A raw password * @param string $salt The salt * * @return Boolean true if the password is valid, false otherwise */ public function isPasswordValid($encoded, $raw, $salt); } PK]W"RRSecurity/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; /** * Glob matches globbing patterns against text. * * if match_glob("foo.*", "foo.bar") echo "matched\n"; * * // prints foo.bar and foo.baz * $regex = glob_to_regex("foo.*"); * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t) * { * if (/$regex/) echo "matched: $car\n"; * } * * Glob implements glob(3) style matching that can be used to match * against text, rather than fetching names from a filesystem. * * Based on the Perl Text::Glob module. * * @author Fabien Potencier PHP port * @author Richard Clamp Perl version * @copyright 2004-2005 Fabien Potencier * @copyright 2002 Richard Clamp */ class Glob { /** * Returns a regexp which is the equivalent of the glob pattern. * * @param string $glob The glob pattern * @param Boolean $strictLeadingDot * @param Boolean $strictWildcardSlash * * @return string regex The regexp */ public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true) { $firstByte = true; $escaping = false; $inCurlies = 0; $regex = ''; $sizeGlob = strlen($glob); for ($i = 0; $i < $sizeGlob; $i++) { $car = $glob[$i]; if ($firstByte) { if ($strictLeadingDot && '.' !== $car) { $regex .= '(?=[^\.])'; } $firstByte = false; } if ('/' === $car) { $firstByte = true; } if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { $regex .= "\\$car"; } elseif ('*' === $car) { $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); } elseif ('?' === $car) { $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); } elseif ('{' === $car) { $regex .= $escaping ? '\\{' : '('; if (!$escaping) { ++$inCurlies; } } elseif ('}' === $car && $inCurlies) { $regex .= $escaping ? '}' : ')'; if (!$escaping) { --$inCurlies; } } elseif (',' === $car && $inCurlies) { $regex .= $escaping ? ',' : '|'; } elseif ('\\' === $car) { if ($escaping) { $regex .= '\\\\'; $escaping = false; } else { $escaping = true; } continue; } else { $regex .= $car; } $escaping = false; } return '#^'.$regex.'$#'; } } PK]59Finder/SplFileInfo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; /** * Extends \SplFileInfo to support relative paths * * @author Fabien Potencier */ class SplFileInfo extends \SplFileInfo { private $relativePath; private $relativePathname; /** * Constructor * * @param string $file The file name * @param string $relativePath The relative path * @param string $relativePathname The relative path name */ public function __construct($file, $relativePath, $relativePathname) { parent::__construct($file); $this->relativePath = $relativePath; $this->relativePathname = $relativePathname; } /** * Returns the relative path * * @return string the relative path */ public function getRelativePath() { return $this->relativePath; } /** * Returns the relative path name * * @return string the relative path name */ public function getRelativePathname() { return $this->relativePathname; } /** * Returns the contents of the file * * @return string the contents of the file * * @throws \RuntimeException */ public function getContents() { $level = error_reporting(0); $content = file_get_contents($this->getPathname()); error_reporting($level); if (false === $content) { $error = error_get_last(); throw new \RuntimeException($error['message']); } return $content; } } PK]P  &Finder/Comparator/NumberComparator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * NumberComparator compiles a simple comparison to an anonymous * subroutine, which you can call with a value to be tested again. * * Now this would be very pointless, if NumberCompare didn't understand * magnitudes. * * The target value may use magnitudes of kilobytes (k, ki), * megabytes (m, mi), or gigabytes (g, gi). Those suffixed * with an i use the appropriate 2**n version in accordance with the * IEC standard: http://physics.nist.gov/cuu/Units/binary.html * * Based on the Perl Number::Compare module. * * @author Fabien Potencier PHP port * @author Richard Clamp Perl version * * @copyright 2004-2005 Fabien Potencier * @copyright 2002 Richard Clamp * * @see http://physics.nist.gov/cuu/Units/binary.html */ class NumberComparator extends Comparator { /** * Constructor. * * @param string $test A comparison string * * @throws \InvalidArgumentException If the test is not understood */ public function __construct($test) { if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test)); } $target = $matches[2]; if (!is_numeric($target)) { throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target)); } if (isset($matches[3])) { // magnitude switch (strtolower($matches[3])) { case 'k': $target *= 1000; break; case 'ki': $target *= 1024; break; case 'm': $target *= 1000000; break; case 'mi': $target *= 1024*1024; break; case 'g': $target *= 1000000000; break; case 'gi': $target *= 1024*1024*1024; break; } } $this->setTarget($target); $this->setOperator(isset($matches[1]) ? $matches[1] : '=='); } } PK]|Fz   Finder/Comparator/Comparator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * Comparator. * * @author Fabien Potencier */ class Comparator { private $target; private $operator = '=='; /** * Gets the target value. * * @return string The target value */ public function getTarget() { return $this->target; } /** * Sets the target value. * * @param string $target The target value */ public function setTarget($target) { $this->target = $target; } /** * Gets the comparison operator. * * @return string The operator */ public function getOperator() { return $this->operator; } /** * Sets the comparison operator. * * @param string $operator A valid operator * * @throws \InvalidArgumentException */ public function setOperator($operator) { if (!$operator) { $operator = '=='; } if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) { throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); } $this->operator = $operator; } /** * Tests against the target. * * @param mixed $test A test value * * @return Boolean */ public function test($test) { switch ($this->operator) { case '>': return $test > $this->target; case '>=': return $test >= $this->target; case '<': return $test < $this->target; case '<=': return $test <= $this->target; case '!=': return $test != $this->target; } return $test == $this->target; } } PK] $Finder/Comparator/DateComparator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * DateCompare compiles date comparisons. * * @author Fabien Potencier */ class DateComparator extends Comparator { /** * Constructor. * * @param string $test A comparison string * * @throws \InvalidArgumentException If the test is not understood */ public function __construct($test) { if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); } try { $date = new \DateTime($matches[2]); $target = $date->format('U'); } catch (\Exception $e) { throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); } $operator = isset($matches[1]) ? $matches[1] : '=='; if ('since' === $operator || 'after' === $operator) { $operator = '>'; } if ('until' === $operator || 'before' === $operator) { $operator = '<'; } $this->setOperator($operator); $this->setTarget($target); } } PK]7'Finder/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ interface ExceptionInterface { /** * @return \Symfony\Component\Finder\Adapter\AdapterInterface */ public function getAdapter(); } PK]cWޫ*Finder/Exception/AccessDeniedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ class AccessDeniedException extends \UnexpectedValueException { } PK]P2Finder/Exception/OperationNotPermitedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ class OperationNotPermitedException extends AdapterFailureException { } PK]991Finder/Exception/ShellCommandFailureException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; use Symfony\Component\Finder\Adapter\AdapterInterface; use Symfony\Component\Finder\Shell\Command; /** * @author Jean-François Simon */ class ShellCommandFailureException extends AdapterFailureException { /** * @var Command */ private $command; /** * @param AdapterInterface $adapter * @param Command $command * @param \Exception|null $previous */ public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null) { $this->command = $command; parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous); } /** * @return Command */ public function getCommand() { return $this->command; } } PK]>@,Finder/Exception/AdapterFailureException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; use Symfony\Component\Finder\Adapter\AdapterInterface; /** * Base exception for all adapter failures. * * @author Jean-François Simon */ class AdapterFailureException extends \RuntimeException implements ExceptionInterface { /** * @var \Symfony\Component\Finder\Adapter\AdapterInterface */ private $adapter; /** * @param AdapterInterface $adapter * @param string|null $message * @param \Exception|null $previous */ public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null) { $this->adapter = $adapter; parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous); } /** * {@inheritdoc} */ public function getAdapter() { return $this->adapter; } } PK]EFinder/Expression/Glob.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Glob implements ValueInterface { /** * @var string */ private $pattern; /** * @param string $pattern */ public function __construct($pattern) { $this->pattern = $pattern; } /** * {@inheritdoc} */ public function render() { return $this->pattern; } /** * {@inheritdoc} */ public function renderPattern() { return $this->pattern; } /** * {@inheritdoc} */ public function getType() { return Expression::TYPE_GLOB; } /** * {@inheritdoc} */ public function isCaseSensitive() { return true; } /** * {@inheritdoc} */ public function prepend($expr) { $this->pattern = $expr.$this->pattern; return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->pattern .= $expr; return $this; } /** * Tests if glob is expandable ("*.{a,b}" syntax). * * @return bool */ public function isExpandable() { return false !== strpos($this->pattern, '{') && false !== strpos($this->pattern, '}'); } /** * @param bool $strictLeadingDot * @param bool $strictWildcardSlash * * @return Regex */ public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true) { $firstByte = true; $escaping = false; $inCurlies = 0; $regex = ''; $sizeGlob = strlen($this->pattern); for ($i = 0; $i < $sizeGlob; $i++) { $car = $this->pattern[$i]; if ($firstByte) { if ($strictLeadingDot && '.' !== $car) { $regex .= '(?=[^\.])'; } $firstByte = false; } if ('/' === $car) { $firstByte = true; } if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { $regex .= "\\$car"; } elseif ('*' === $car) { $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); } elseif ('?' === $car) { $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); } elseif ('{' === $car) { $regex .= $escaping ? '\\{' : '('; if (!$escaping) { ++$inCurlies; } } elseif ('}' === $car && $inCurlies) { $regex .= $escaping ? '}' : ')'; if (!$escaping) { --$inCurlies; } } elseif (',' === $car && $inCurlies) { $regex .= $escaping ? ',' : '|'; } elseif ('\\' === $car) { if ($escaping) { $regex .= '\\\\'; $escaping = false; } else { $escaping = true; } continue; } else { $regex .= $car; } $escaping = false; } return new Regex('^'.$regex.'$'); } } PK](Finder/Expression/Regex.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Regex implements ValueInterface { const START_FLAG = '^'; const END_FLAG = '$'; const BOUNDARY = '~'; const JOKER = '.*'; const ESCAPING = '\\'; /** * @var string */ private $pattern; /** * @var array */ private $options; /** * @var bool */ private $startFlag; /** * @var bool */ private $endFlag; /** * @var bool */ private $startJoker; /** * @var bool */ private $endJoker; /** * @param string $expr * * @return Regex * * @throws \InvalidArgumentException */ public static function create($expr) { if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) { $start = substr($m[1], 0, 1); $end = substr($m[1], -1); if ( ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start)) || ($start === '{' && $end === '}') || ($start === '(' && $end === ')') ) { return new self(substr($m[1], 1, -1), $m[2], $end); } } throw new \InvalidArgumentException('Given expression is not a regex.'); } /** * @param string $pattern * @param string $options * @param string $delimiter */ public function __construct($pattern, $options = '', $delimiter = null) { if (null !== $delimiter) { // removes delimiter escaping $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern); } $this->parsePattern($pattern); $this->options = $options; } /** * @return string */ public function __toString() { return $this->render(); } /** * {@inheritdoc} */ public function render() { return self::BOUNDARY .$this->renderPattern() .self::BOUNDARY .$this->options; } /** * {@inheritdoc} */ public function renderPattern() { return ($this->startFlag ? self::START_FLAG : '') .($this->startJoker ? self::JOKER : '') .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern) .($this->endJoker ? self::JOKER : '') .($this->endFlag ? self::END_FLAG : ''); } /** * {@inheritdoc} */ public function isCaseSensitive() { return !$this->hasOption('i'); } /** * {@inheritdoc} */ public function getType() { return Expression::TYPE_REGEX; } /** * {@inheritdoc} */ public function prepend($expr) { $this->pattern = $expr.$this->pattern; return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->pattern .= $expr; return $this; } /** * @param string $option * * @return bool */ public function hasOption($option) { return false !== strpos($this->options, $option); } /** * @param string $option * * @return Regex */ public function addOption($option) { if (!$this->hasOption($option)) { $this->options.= $option; } return $this; } /** * @param string $option * * @return Regex */ public function removeOption($option) { $this->options = str_replace($option, '', $this->options); return $this; } /** * @param bool $startFlag * * @return Regex */ public function setStartFlag($startFlag) { $this->startFlag = $startFlag; return $this; } /** * @return bool */ public function hasStartFlag() { return $this->startFlag; } /** * @param bool $endFlag * * @return Regex */ public function setEndFlag($endFlag) { $this->endFlag = (bool) $endFlag; return $this; } /** * @return bool */ public function hasEndFlag() { return $this->endFlag; } /** * @param bool $startJoker * * @return Regex */ public function setStartJoker($startJoker) { $this->startJoker = $startJoker; return $this; } /** * @return bool */ public function hasStartJoker() { return $this->startJoker; } /** * @param bool $endJoker * * @return Regex */ public function setEndJoker($endJoker) { $this->endJoker = (bool) $endJoker; return $this; } /** * @return bool */ public function hasEndJoker() { return $this->endJoker; } /** * @param array $replacement * * @return Regex */ public function replaceJokers($replacement) { $replace = function ($subject) use ($replacement) { $subject = $subject[0]; $replace = 0 === substr_count($subject, '\\') % 2; return $replace ? str_replace('.', $replacement, $subject) : $subject; }; $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern); return $this; } /** * @param string $pattern */ private function parsePattern($pattern) { if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) { $pattern = substr($pattern, 1); } if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) { $pattern = substr($pattern, 2); } if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) { $pattern = substr($pattern, 0, -1); } if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) { $pattern = substr($pattern, 0, -2); } $this->pattern = $pattern; } } PK]"HH$Finder/Expression/ValueInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ interface ValueInterface { /** * Renders string representation of expression. * * @return string */ public function render(); /** * Renders string representation of pattern. * * @return string */ public function renderPattern(); /** * Returns value case sensitivity. * * @return bool */ public function isCaseSensitive(); /** * Returns expression type. * * @return int */ public function getType(); /** * @param string $expr * * @return ValueInterface */ public function prepend($expr); /** * @param string $expr * * @return ValueInterface */ public function append($expr); } PK] & & Finder/Expression/Expression.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Expression implements ValueInterface { const TYPE_REGEX = 1; const TYPE_GLOB = 2; /** * @var ValueInterface */ private $value; /** * @param string $expr * * @return Expression */ public static function create($expr) { return new self($expr); } /** * @param string $expr */ public function __construct($expr) { try { $this->value = Regex::create($expr); } catch (\InvalidArgumentException $e) { $this->value = new Glob($expr); } } /** * @return string */ public function __toString() { return $this->render(); } /** * {@inheritdoc} */ public function render() { return $this->value->render(); } /** * {@inheritdoc} */ public function renderPattern() { return $this->value->renderPattern(); } /** * @return bool */ public function isCaseSensitive() { return $this->value->isCaseSensitive(); } /** * @return int */ public function getType() { return $this->value->getType(); } /** * {@inheritdoc} */ public function prepend($expr) { $this->value->prepend($expr); return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->value->append($expr); return $this; } /** * @return bool */ public function isRegex() { return self::TYPE_REGEX === $this->value->getType(); } /** * @return bool */ public function isGlob() { return self::TYPE_GLOB === $this->value->getType(); } /** * @throws \LogicException * * @return Glob */ public function getGlob() { if (self::TYPE_GLOB !== $this->value->getType()) { throw new \LogicException('Regex can\'t be transformed to glob.'); } return $this->value; } /** * @return Regex */ public function getRegex() { return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex(); } } PK]4˵Finder/Shell/Shell.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Shell; /** * @author Jean-François Simon */ class Shell { const TYPE_UNIX = 1; const TYPE_DARWIN = 2; const TYPE_CYGWIN = 3; const TYPE_WINDOWS = 4; const TYPE_BSD = 5; /** * @var string|null */ private $type; /** * Returns guessed OS type. * * @return int */ public function getType() { if (null === $this->type) { $this->type = $this->guessType(); } return $this->type; } /** * Tests if a command is available. * * @param string $command * * @return bool */ public function testCommand($command) { if (self::TYPE_WINDOWS === $this->type) { // todo: find a way to test if Windows command exists return false; } if (!function_exists('exec')) { return false; } // todo: find a better way (command could not be available) exec('command -v '.$command, $output, $code); return 0 === $code && count($output) > 0; } /** * Guesses OS type. * * @return int */ private function guessType() { $os = strtolower(PHP_OS); if (false !== strpos($os, 'cygwin')) { return self::TYPE_CYGWIN; } if (false !== strpos($os, 'darwin')) { return self::TYPE_DARWIN; } if (false !== strpos($os, 'bsd')) { return self::TYPE_BSD; } if (0 === strpos($os, 'win')) { return self::TYPE_WINDOWS; } return self::TYPE_UNIX; } } PK]5KFinder/Shell/Command.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Shell; /** * @author Jean-François Simon */ class Command { /** * @var Command|null */ private $parent; /** * @var array */ private $bits = array(); /** * @var array */ private $labels = array(); /** * @var \Closure|null */ private $errorHandler; /** * Constructor. * * @param Command|null $parent Parent command */ public function __construct(Command $parent = null) { $this->parent = $parent; } /** * Returns command as string. * * @return string */ public function __toString() { return $this->join(); } /** * Creates a new Command instance. * * @param Command|null $parent Parent command * * @return Command New Command instance */ public static function create(Command $parent = null) { return new self($parent); } /** * Escapes special chars from input. * * @param string $input A string to escape * * @return string The escaped string */ public static function escape($input) { return escapeshellcmd($input); } /** * Quotes input. * * @param string $input An argument string * * @return string The quoted string */ public static function quote($input) { return escapeshellarg($input); } /** * Appends a string or a Command instance. * * @param string|Command $bit * * @return Command The current Command instance */ public function add($bit) { $this->bits[] = $bit; return $this; } /** * Prepends a string or a command instance. * * @param string|Command $bit * * @return Command The current Command instance */ public function top($bit) { array_unshift($this->bits, $bit); foreach ($this->labels as $label => $index) { $this->labels[$label] += 1; } return $this; } /** * Appends an argument, will be quoted. * * @param string $arg * * @return Command The current Command instance */ public function arg($arg) { $this->bits[] = self::quote($arg); return $this; } /** * Appends escaped special command chars. * * @param string $esc * * @return Command The current Command instance */ public function cmd($esc) { $this->bits[] = self::escape($esc); return $this; } /** * Inserts a labeled command to feed later. * * @param string $label The unique label * * @return Command The current Command instance * * @throws \RuntimeException If label already exists */ public function ins($label) { if (isset($this->labels[$label])) { throw new \RuntimeException(sprintf('Label "%s" already exists.', $label)); } $this->bits[] = self::create($this); $this->labels[$label] = count($this->bits)-1; return $this->bits[$this->labels[$label]]; } /** * Retrieves a previously labeled command. * * @param string $label * * @return Command The labeled command * * @throws \RuntimeException */ public function get($label) { if (!isset($this->labels[$label])) { throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label)); } return $this->bits[$this->labels[$label]]; } /** * Returns parent command (if any). * * @return Command Parent command * * @throws \RuntimeException If command has no parent */ public function end() { if (null === $this->parent) { throw new \RuntimeException('Calling end on root command doesn\'t make sense.'); } return $this->parent; } /** * Counts bits stored in command. * * @return int The bits count */ public function length() { return count($this->bits); } /** * @param \Closure $errorHandler * * @return Command */ public function setErrorHandler(\Closure $errorHandler) { $this->errorHandler = $errorHandler; return $this; } /** * @return \Closure|null */ public function getErrorHandler() { return $this->errorHandler; } /** * Executes current command. * * @return array The command result * * @throws \RuntimeException */ public function execute() { if (null === $this->errorHandler) { exec($this->join(), $output); } else { $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes); $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY); if ($error = stream_get_contents($pipes[2])) { call_user_func($this->errorHandler, $error); } proc_close($process); } return $output ?: array(); } /** * Joins bits. * * @return string */ public function join() { return implode(' ', array_filter( array_map(function ($bit) { return $bit instanceof Command ? $bit->join() : ($bit ?: null); }, $this->bits), function ($bit) { return null !== $bit; } )); } /** * Insert a string or a Command instance before the bit at given position $index (index starts from 0). * * @param string|Command $bit * @param integer $index * * @return Command The current Command instance */ public function addAtIndex($bit, $index) { array_splice($this->bits, $index, 0, $bit); return $this; } } PK]9!2{ { Finder/Adapter/PhpAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Iterator; /** * PHP finder engine implementation. * * @author Jean-François Simon */ class PhpAdapter extends AbstractAdapter { /** * {@inheritdoc} */ public function searchInDirectory($dir) { $flags = \RecursiveDirectoryIterator::SKIP_DOTS; if ($this->followLinks) { $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; } $iterator = new \RecursiveIteratorIterator( new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs), \RecursiveIteratorIterator::SELF_FIRST ); if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) { $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth); } if ($this->mode) { $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); } if ($this->exclude) { $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); } if ($this->names || $this->notNames) { $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); } if ($this->contains || $this->notContains) { $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); } if ($this->sizes) { $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes); } if ($this->dates) { $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates); } if ($this->filters) { $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } if ($this->sort) { $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); $iterator = $iteratorAggregate->getIterator(); } if ($this->paths || $this->notPaths) { $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths); } return $iterator; } /** * {@inheritdoc} */ public function getName() { return 'php'; } /** * {@inheritdoc} */ protected function canBeUsed() { return true; } } PK] "Finder/Adapter/AbstractAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; /** * Interface for finder engine implementations. * * @author Jean-François Simon */ abstract class AbstractAdapter implements AdapterInterface { protected $followLinks = false; protected $mode = 0; protected $minDepth = 0; protected $maxDepth = PHP_INT_MAX; protected $exclude = array(); protected $names = array(); protected $notNames = array(); protected $contains = array(); protected $notContains = array(); protected $sizes = array(); protected $dates = array(); protected $filters = array(); protected $sort = false; protected $paths = array(); protected $notPaths = array(); protected $ignoreUnreadableDirs = false; private static $areSupported = array(); /** * {@inheritDoc} */ public function isSupported() { $name = $this->getName(); if (!array_key_exists($name, self::$areSupported)) { self::$areSupported[$name] = $this->canBeUsed(); } return self::$areSupported[$name]; } /** * {@inheritdoc} */ public function setFollowLinks($followLinks) { $this->followLinks = $followLinks; return $this; } /** * {@inheritdoc} */ public function setMode($mode) { $this->mode = $mode; return $this; } /** * {@inheritdoc} */ public function setDepths(array $depths) { $this->minDepth = 0; $this->maxDepth = PHP_INT_MAX; foreach ($depths as $comparator) { switch ($comparator->getOperator()) { case '>': $this->minDepth = $comparator->getTarget() + 1; break; case '>=': $this->minDepth = $comparator->getTarget(); break; case '<': $this->maxDepth = $comparator->getTarget() - 1; break; case '<=': $this->maxDepth = $comparator->getTarget(); break; default: $this->minDepth = $this->maxDepth = $comparator->getTarget(); } } return $this; } /** * {@inheritdoc} */ public function setExclude(array $exclude) { $this->exclude = $exclude; return $this; } /** * {@inheritdoc} */ public function setNames(array $names) { $this->names = $names; return $this; } /** * {@inheritdoc} */ public function setNotNames(array $notNames) { $this->notNames = $notNames; return $this; } /** * {@inheritdoc} */ public function setContains(array $contains) { $this->contains = $contains; return $this; } /** * {@inheritdoc} */ public function setNotContains(array $notContains) { $this->notContains = $notContains; return $this; } /** * {@inheritdoc} */ public function setSizes(array $sizes) { $this->sizes = $sizes; return $this; } /** * {@inheritdoc} */ public function setDates(array $dates) { $this->dates = $dates; return $this; } /** * {@inheritdoc} */ public function setFilters(array $filters) { $this->filters = $filters; return $this; } /** * {@inheritdoc} */ public function setSort($sort) { $this->sort = $sort; return $this; } /** * {@inheritdoc} */ public function setPath(array $paths) { $this->paths = $paths; return $this; } /** * {@inheritdoc} */ public function setNotPath(array $notPaths) { $this->notPaths = $notPaths; return $this; } /** * {@inheritdoc} */ public function ignoreUnreadableDirs($ignore = true) { $this->ignoreUnreadableDirs = (Boolean) $ignore; return $this; } /** * Returns whether the adapter is supported in the current environment. * * This method should be implemented in all adapters. Do not implement * isSupported in the adapters as the generic implementation provides a cache * layer. * * @see isSupported * * @return Boolean Whether the adapter is supported */ abstract protected function canBeUsed(); } PK]}] !Finder/Adapter/GnuFindAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Iterator\SortableIterator; use Symfony\Component\Finder\Expression\Expression; /** * Shell engine implementation using GNU find command. * * @author Jean-François Simon */ class GnuFindAdapter extends AbstractFindAdapter { /** * {@inheritdoc} */ public function getName() { return 'gnu_find'; } /** * {@inheritdoc} */ protected function buildFormatSorting(Command $command, $sort) { switch ($sort) { case SortableIterator::SORT_BY_NAME: $command->ins('sort')->add('| sort'); return; case SortableIterator::SORT_BY_TYPE: $format = '%y'; break; case SortableIterator::SORT_BY_ACCESSED_TIME: $format = '%A@'; break; case SortableIterator::SORT_BY_CHANGED_TIME: $format = '%C@'; break; case SortableIterator::SORT_BY_MODIFIED_TIME: $format = '%T@'; break; default: throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); } $command ->get('find') ->add('-printf') ->arg($format.' %h/%f\\n') ->add('| sort | cut') ->arg('-d ') ->arg('-f2-') ; } /** * {@inheritdoc} */ protected function canBeUsed() { return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed(); } /** * {@inheritdoc} */ protected function buildFindCommand(Command $command, $dir) { return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended'); } /** * {@inheritdoc} */ protected function buildContentFiltering(Command $command, array $contains, $not = false) { foreach ($contains as $contain) { $expr = Expression::create($contain); // todo: avoid forking process for each $pattern by using multiple -e options $command ->add('| xargs -I{} -r grep -I') ->add($expr->isCaseSensitive() ? null : '-i') ->add($not ? '-L' : '-l') ->add('-Ee')->arg($expr->renderPattern()) ->add('{}') ; } } } PK]QJ))&Finder/Adapter/AbstractFindAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Exception\AccessDeniedException; use Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Expression\Expression; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Iterator\SortableIterator; use Symfony\Component\Finder\Comparator\NumberComparator; use Symfony\Component\Finder\Comparator\DateComparator; /** * Shell engine implementation using GNU find command. * * @author Jean-François Simon */ abstract class AbstractFindAdapter extends AbstractAdapter { /** * @var Shell */ protected $shell; /** * Constructor. */ public function __construct() { $this->shell = new Shell(); } /** * {@inheritdoc} */ public function searchInDirectory($dir) { // having "/../" in path make find fail $dir = realpath($dir); // searching directories containing or not containing strings leads to no result if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) { return new Iterator\FilePathsIterator(array(), $dir); } $command = Command::create(); $find = $this->buildFindCommand($command, $dir); if ($this->followLinks) { $find->add('-follow'); } $find->add('-mindepth')->add($this->minDepth + 1); if (PHP_INT_MAX !== $this->maxDepth) { $find->add('-maxdepth')->add($this->maxDepth + 1); } if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) { $find->add('-type d'); } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) { $find->add('-type f'); } $this->buildNamesFiltering($find, $this->names); $this->buildNamesFiltering($find, $this->notNames, true); $this->buildPathsFiltering($find, $dir, $this->paths); $this->buildPathsFiltering($find, $dir, $this->notPaths, true); $this->buildSizesFiltering($find, $this->sizes); $this->buildDatesFiltering($find, $this->dates); $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs'); $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut'); if ($useGrep && ($this->contains || $this->notContains)) { $grep = $command->ins('grep'); $this->buildContentFiltering($grep, $this->contains); $this->buildContentFiltering($grep, $this->notContains, true); } if ($useSort) { $this->buildSorting($command, $this->sort); } $command->setErrorHandler( $this->ignoreUnreadableDirs // If directory is unreadable and finder is set to ignore it, `stderr` is ignored. ? function ($stderr) { return; } : function ($stderr) { throw new AccessDeniedException($stderr); } ); $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute()); $iterator = new Iterator\FilePathsIterator($paths, $dir); if ($this->exclude) { $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); } if (!$useGrep && ($this->contains || $this->notContains)) { $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); } if ($this->filters) { $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } if (!$useSort && $this->sort) { $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); $iterator = $iteratorAggregate->getIterator(); } return $iterator; } /** * {@inheritdoc} */ protected function canBeUsed() { return $this->shell->testCommand('find'); } /** * @param Command $command * @param string $dir * * @return Command */ protected function buildFindCommand(Command $command, $dir) { return $command ->ins('find') ->add('find ') ->arg($dir) ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions } /** * @param Command $command * @param string[] $names * @param Boolean $not */ private function buildNamesFiltering(Command $command, array $names, $not = false) { if (0 === count($names)) { return; } $command->add($not ? '-not' : null)->cmd('('); foreach ($names as $i => $name) { $expr = Expression::create($name); // Find does not support expandable globs ("*.{a,b}" syntax). if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { $expr = Expression::create($expr->getGlob()->toRegex(false)); } // Fixes 'not search' and 'full path matching' regex problems. // - Jokers '.' are replaced by [^/]. // - We add '[^/]*' before and after regex (if no ^|$ flags are present). if ($expr->isRegex()) { $regex = $expr->getRegex(); $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*') ->setStartFlag(false) ->setStartJoker(true) ->replaceJokers('[^/]'); if (!$regex->hasEndFlag() || $regex->hasEndJoker()) { $regex->setEndJoker(false)->append('[^/]*'); } } $command ->add($i > 0 ? '-or' : null) ->add($expr->isRegex() ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') : ($expr->isCaseSensitive() ? '-name' : '-iname') ) ->arg($expr->renderPattern()); } $command->cmd(')'); } /** * @param Command $command * @param string $dir * @param string[] $paths * @param Boolean $not */ private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false) { if (0 === count($paths)) { return; } $command->add($not ? '-not' : null)->cmd('('); foreach ($paths as $i => $path) { $expr = Expression::create($path); // Find does not support expandable globs ("*.{a,b}" syntax). if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { $expr = Expression::create($expr->getGlob()->toRegex(false)); } // Fixes 'not search' regex problems. if ($expr->isRegex()) { $regex = $expr->getRegex(); $regex->prepend($regex->hasStartFlag() ? $dir.DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag()); } else { $expr->prepend('*')->append('*'); } $command ->add($i > 0 ? '-or' : null) ->add($expr->isRegex() ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') : ($expr->isCaseSensitive() ? '-path' : '-ipath') ) ->arg($expr->renderPattern()); } $command->cmd(')'); } /** * @param Command $command * @param NumberComparator[] $sizes */ private function buildSizesFiltering(Command $command, array $sizes) { foreach ($sizes as $i => $size) { $command->add($i > 0 ? '-and' : null); switch ($size->getOperator()) { case '<=': $command->add('-size -'.($size->getTarget() + 1).'c'); break; case '>=': $command->add('-size +'. ($size->getTarget() - 1).'c'); break; case '>': $command->add('-size +'.$size->getTarget().'c'); break; case '!=': $command->add('-size -'.$size->getTarget().'c'); $command->add('-size +'.$size->getTarget().'c'); case '<': default: $command->add('-size -'.$size->getTarget().'c'); } } } /** * @param Command $command * @param DateComparator[] $dates */ private function buildDatesFiltering(Command $command, array $dates) { foreach ($dates as $i => $date) { $command->add($i > 0 ? '-and' : null); $mins = (int) round((time()-$date->getTarget()) / 60); if (0 > $mins) { // mtime is in the future $command->add(' -mmin -0'); // we will have no result so we don't need to continue return; } switch ($date->getOperator()) { case '<=': $command->add('-mmin +'.($mins - 1)); break; case '>=': $command->add('-mmin -'.($mins + 1)); break; case '>': $command->add('-mmin -'.$mins); break; case '!=': $command->add('-mmin +'.$mins.' -or -mmin -'.$mins); break; case '<': default: $command->add('-mmin +'.$mins); } } } /** * @param Command $command * @param string $sort * * @throws \InvalidArgumentException */ private function buildSorting(Command $command, $sort) { $this->buildFormatSorting($command, $sort); } /** * @param Command $command * @param string $sort */ abstract protected function buildFormatSorting(Command $command, $sort); /** * @param Command $command * @param array $contains * @param Boolean $not */ abstract protected function buildContentFiltering(Command $command, array $contains, $not = false); } PK]kA !Finder/Adapter/BsdFindAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Iterator\SortableIterator; use Symfony\Component\Finder\Expression\Expression; /** * Shell engine implementation using BSD find command. * * @author Jean-François Simon */ class BsdFindAdapter extends AbstractFindAdapter { /** * {@inheritdoc} */ public function getName() { return 'bsd_find'; } /** * {@inheritdoc} */ protected function canBeUsed() { return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed(); } /** * {@inheritdoc} */ protected function buildFormatSorting(Command $command, $sort) { switch ($sort) { case SortableIterator::SORT_BY_NAME: $command->ins('sort')->add('| sort'); return; case SortableIterator::SORT_BY_TYPE: $format = '%HT'; break; case SortableIterator::SORT_BY_ACCESSED_TIME: $format = '%a'; break; case SortableIterator::SORT_BY_CHANGED_TIME: $format = '%c'; break; case SortableIterator::SORT_BY_MODIFIED_TIME: $format = '%m'; break; default: throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); } $command ->add('-print0 | xargs -0 stat -f') ->arg($format.'%t%N') ->add('| sort | cut -f 2'); } /** * {@inheritdoc} */ protected function buildFindCommand(Command $command, $dir) { parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1); return $command; } /** * {@inheritdoc} */ protected function buildContentFiltering(Command $command, array $contains, $not = false) { foreach ($contains as $contain) { $expr = Expression::create($contain); // todo: avoid forking process for each $pattern by using multiple -e options $command ->add('| grep -v \'^$\'') ->add('| xargs -I{} grep -I') ->add($expr->isCaseSensitive() ? null : '-i') ->add($not ? '-L' : '-l') ->add('-Ee')->arg($expr->renderPattern()) ->add('{}') ; } } } PK] #Finder/Adapter/AdapterInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; /** * @author Jean-François Simon */ interface AdapterInterface { /** * @param Boolean $followLinks * * @return AdapterInterface Current instance */ public function setFollowLinks($followLinks); /** * @param integer $mode * * @return AdapterInterface Current instance */ public function setMode($mode); /** * @param array $exclude * * @return AdapterInterface Current instance */ public function setExclude(array $exclude); /** * @param array $depths * * @return AdapterInterface Current instance */ public function setDepths(array $depths); /** * @param array $names * * @return AdapterInterface Current instance */ public function setNames(array $names); /** * @param array $notNames * * @return AdapterInterface Current instance */ public function setNotNames(array $notNames); /** * @param array $contains * * @return AdapterInterface Current instance */ public function setContains(array $contains); /** * @param array $notContains * * @return AdapterInterface Current instance */ public function setNotContains(array $notContains); /** * @param array $sizes * * @return AdapterInterface Current instance */ public function setSizes(array $sizes); /** * @param array $dates * * @return AdapterInterface Current instance */ public function setDates(array $dates); /** * @param array $filters * * @return AdapterInterface Current instance */ public function setFilters(array $filters); /** * @param \Closure|integer $sort * * @return AdapterInterface Current instance */ public function setSort($sort); /** * @param array $paths * * @return AdapterInterface Current instance */ public function setPath(array $paths); /** * @param array $notPaths * * @return AdapterInterface Current instance */ public function setNotPath(array $notPaths); /** * @param boolean $ignore * * @return AdapterInterface Current instance */ public function ignoreUnreadableDirs($ignore = true); /** * @param string $dir * * @return \Iterator Result iterator */ public function searchInDirectory($dir); /** * Tests adapter support for current platform. * * @return Boolean */ public function isSupported(); /** * Returns adapter name. * * @return string */ public function getName(); } PK]dVVFinder/Finder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; use Symfony\Component\Finder\Adapter\AdapterInterface; use Symfony\Component\Finder\Adapter\GnuFindAdapter; use Symfony\Component\Finder\Adapter\BsdFindAdapter; use Symfony\Component\Finder\Adapter\PhpAdapter; use Symfony\Component\Finder\Exception\ExceptionInterface; /** * Finder allows to build rules to find files and directories. * * It is a thin wrapper around several specialized iterator classes. * * All rules may be invoked several times. * * All methods return the current Finder object to allow easy chaining: * * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); * * @author Fabien Potencier * * @api */ class Finder implements \IteratorAggregate, \Countable { const IGNORE_VCS_FILES = 1; const IGNORE_DOT_FILES = 2; private $mode = 0; private $names = array(); private $notNames = array(); private $exclude = array(); private $filters = array(); private $depths = array(); private $sizes = array(); private $followLinks = false; private $sort = false; private $ignore = 0; private $dirs = array(); private $dates = array(); private $iterators = array(); private $contains = array(); private $notContains = array(); private $adapters = array(); private $paths = array(); private $notPaths = array(); private $ignoreUnreadableDirs = false; private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'); /** * Constructor. */ public function __construct() { $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; $this ->addAdapter(new GnuFindAdapter()) ->addAdapter(new BsdFindAdapter()) ->addAdapter(new PhpAdapter(), -50) ->setAdapter('php') ; } /** * Creates a new Finder. * * @return Finder A new Finder instance * * @api */ public static function create() { return new static(); } /** * Registers a finder engine implementation. * * @param AdapterInterface $adapter An adapter instance * @param integer $priority Highest is selected first * * @return Finder The current Finder instance */ public function addAdapter(Adapter\AdapterInterface $adapter, $priority = 0) { $this->adapters[$adapter->getName()] = array( 'adapter' => $adapter, 'priority' => $priority, 'selected' => false, ); return $this->sortAdapters(); } /** * Sets the selected adapter to the best one according to the current platform the code is run on. * * @return Finder The current Finder instance */ public function useBestAdapter() { $this->resetAdapterSelection(); return $this->sortAdapters(); } /** * Selects the adapter to use. * * @param string $name * * @throws \InvalidArgumentException * * @return Finder The current Finder instance */ public function setAdapter($name) { if (!isset($this->adapters[$name])) { throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name)); } $this->resetAdapterSelection(); $this->adapters[$name]['selected'] = true; return $this->sortAdapters(); } /** * Removes all adapters registered in the finder. * * @return Finder The current Finder instance */ public function removeAdapters() { $this->adapters = array(); return $this; } /** * Returns registered adapters ordered by priority without extra information. * * @return AdapterInterface[] */ public function getAdapters() { return array_values(array_map(function (array $adapter) { return $adapter['adapter']; }, $this->adapters)); } /** * Restricts the matching to directories only. * * @return Finder The current Finder instance * * @api */ public function directories() { $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES; return $this; } /** * Restricts the matching to files only. * * @return Finder The current Finder instance * * @api */ public function files() { $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES; return $this; } /** * Adds tests for the directory depth. * * Usage: * * $finder->depth('> 1') // the Finder will start matching at level 1. * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. * * @param int $level The depth level expression * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\DepthRangeFilterIterator * @see Symfony\Component\Finder\Comparator\NumberComparator * * @api */ public function depth($level) { $this->depths[] = new Comparator\NumberComparator($level); return $this; } /** * Adds tests for file dates (last modified). * * The date must be something that strtotime() is able to parse: * * $finder->date('since yesterday'); * $finder->date('until 2 days ago'); * $finder->date('> now - 2 hours'); * $finder->date('>= 2005-10-15'); * * @param string $date A date rage string * * @return Finder The current Finder instance * * @see strtotime * @see Symfony\Component\Finder\Iterator\DateRangeFilterIterator * @see Symfony\Component\Finder\Comparator\DateComparator * * @api */ public function date($date) { $this->dates[] = new Comparator\DateComparator($date); return $this; } /** * Adds rules that files must match. * * You can use patterns (delimited with / sign), globs or simple strings. * * $finder->name('*.php') * $finder->name('/\.php$/') // same as above * $finder->name('test.php') * * @param string $pattern A pattern (a regexp, a glob, or a string) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator * * @api */ public function name($pattern) { $this->names[] = $pattern; return $this; } /** * Adds rules that files must not match. * * @param string $pattern A pattern (a regexp, a glob, or a string) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator * * @api */ public function notName($pattern) { $this->notNames[] = $pattern; return $this; } /** * Adds tests that file contents must match. * * Strings or PCRE patterns can be used: * * $finder->contains('Lorem ipsum') * $finder->contains('/Lorem ipsum/i') * * @param string $pattern A pattern (string or regexp) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator */ public function contains($pattern) { $this->contains[] = $pattern; return $this; } /** * Adds tests that file contents must not match. * * Strings or PCRE patterns can be used: * * $finder->notContains('Lorem ipsum') * $finder->notContains('/Lorem ipsum/i') * * @param string $pattern A pattern (string or regexp) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator */ public function notContains($pattern) { $this->notContains[] = $pattern; return $this; } /** * Adds rules that filenames must match. * * You can use patterns (delimited with / sign) or simple strings. * * $finder->path('some/special/dir') * $finder->path('/some\/special\/dir/') // same as above * * Use only / as dirname separator. * * @param string $pattern A pattern (a regexp or a string) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator */ public function path($pattern) { $this->paths[] = $pattern; return $this; } /** * Adds rules that filenames must not match. * * You can use patterns (delimited with / sign) or simple strings. * * $finder->notPath('some/special/dir') * $finder->notPath('/some\/special\/dir/') // same as above * * Use only / as dirname separator. * * @param string $pattern A pattern (a regexp or a string) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator */ public function notPath($pattern) { $this->notPaths[] = $pattern; return $this; } /** * Adds tests for file sizes. * * $finder->size('> 10K'); * $finder->size('<= 1Ki'); * $finder->size(4); * * @param string $size A size range string * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SizeRangeFilterIterator * @see Symfony\Component\Finder\Comparator\NumberComparator * * @api */ public function size($size) { $this->sizes[] = new Comparator\NumberComparator($size); return $this; } /** * Excludes directories. * * @param string|array $dirs A directory path or an array of directories * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator * * @api */ public function exclude($dirs) { $this->exclude = array_merge($this->exclude, (array) $dirs); return $this; } /** * Excludes "hidden" directories and files (starting with a dot). * * @param Boolean $ignoreDotFiles Whether to exclude "hidden" files or not * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator * * @api */ public function ignoreDotFiles($ignoreDotFiles) { if ($ignoreDotFiles) { $this->ignore = $this->ignore | static::IGNORE_DOT_FILES; } else { $this->ignore = $this->ignore & ~static::IGNORE_DOT_FILES; } return $this; } /** * Forces the finder to ignore version control directories. * * @param Boolean $ignoreVCS Whether to exclude VCS files or not * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator * * @api */ public function ignoreVCS($ignoreVCS) { if ($ignoreVCS) { $this->ignore = $this->ignore | static::IGNORE_VCS_FILES; } else { $this->ignore = $this->ignore & ~static::IGNORE_VCS_FILES; } return $this; } /** * Adds VCS patterns. * * @see ignoreVCS * * @param string|string[] $pattern VCS patterns to ignore */ public static function addVCSPattern($pattern) { foreach ((array) $pattern as $p) { self::$vcsPatterns[] = $p; } self::$vcsPatterns = array_unique(self::$vcsPatterns); } /** * Sorts files and directories by an anonymous function. * * The anonymous function receives two \SplFileInfo instances to compare. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @param \Closure $closure An anonymous function * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sort(\Closure $closure) { $this->sort = $closure; return $this; } /** * Sorts files and directories by name. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sortByName() { $this->sort = Iterator\SortableIterator::SORT_BY_NAME; return $this; } /** * Sorts files and directories by type (directories before files), then by name. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sortByType() { $this->sort = Iterator\SortableIterator::SORT_BY_TYPE; return $this; } /** * Sorts files and directories by the last accessed time. * * This is the time that the file was last accessed, read or written to. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sortByAccessedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME; return $this; } /** * Sorts files and directories by the last inode changed time. * * This is the time that the inode information was last modified (permissions, owner, group or other metadata). * * On Windows, since inode is not available, changed time is actually the file creation time. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sortByChangedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME; return $this; } /** * Sorts files and directories by the last modified time. * * This is the last time the actual contents of the file were last modified. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sortByModifiedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME; return $this; } /** * Filters the iterator with an anonymous function. * * The anonymous function receives a \SplFileInfo and must return false * to remove files. * * @param \Closure $closure An anonymous function * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\CustomFilterIterator * * @api */ public function filter(\Closure $closure) { $this->filters[] = $closure; return $this; } /** * Forces the following of symlinks. * * @return Finder The current Finder instance * * @api */ public function followLinks() { $this->followLinks = true; return $this; } /** * Tells finder to ignore unreadable directories. * * By default, scanning unreadable directories content throws an AccessDeniedException. * * @param boolean $ignore * * @return Finder The current Finder instance */ public function ignoreUnreadableDirs($ignore = true) { $this->ignoreUnreadableDirs = (Boolean) $ignore; return $this; } /** * Searches files and directories which match defined rules. * * @param string|array $dirs A directory path or an array of directories * * @return Finder The current Finder instance * * @throws \InvalidArgumentException if one of the directories does not exist * * @api */ public function in($dirs) { $resolvedDirs = array(); foreach ((array) $dirs as $dir) { if (is_dir($dir)) { $resolvedDirs[] = $dir; } elseif ($glob = glob($dir, GLOB_ONLYDIR)) { $resolvedDirs = array_merge($resolvedDirs, $glob); } else { throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir)); } } $this->dirs = array_merge($this->dirs, $resolvedDirs); return $this; } /** * Returns an Iterator for the current Finder configuration. * * This method implements the IteratorAggregate interface. * * @return \Iterator An iterator * * @throws \LogicException if the in() method has not been called */ public function getIterator() { if (0 === count($this->dirs) && 0 === count($this->iterators)) { throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.'); } if (1 === count($this->dirs) && 0 === count($this->iterators)) { return $this->searchInDirectory($this->dirs[0]); } $iterator = new \AppendIterator(); foreach ($this->dirs as $dir) { $iterator->append($this->searchInDirectory($dir)); } foreach ($this->iterators as $it) { $iterator->append($it); } return $iterator; } /** * Appends an existing set of files/directories to the finder. * * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. * * @param mixed $iterator * * @return Finder The finder * * @throws \InvalidArgumentException When the given argument is not iterable. */ public function append($iterator) { if ($iterator instanceof \IteratorAggregate) { $this->iterators[] = $iterator->getIterator(); } elseif ($iterator instanceof \Iterator) { $this->iterators[] = $iterator; } elseif ($iterator instanceof \Traversable || is_array($iterator)) { $it = new \ArrayIterator(); foreach ($iterator as $file) { $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file)); } $this->iterators[] = $it; } else { throw new \InvalidArgumentException('Finder::append() method wrong argument type.'); } return $this; } /** * Counts all the results collected by the iterators. * * @return int */ public function count() { return iterator_count($this->getIterator()); } /** * @return Finder The current Finder instance */ private function sortAdapters() { uasort($this->adapters, function (array $a, array $b) { if ($a['selected'] || $b['selected']) { return $a['selected'] ? -1 : 1; } return $a['priority'] > $b['priority'] ? -1 : 1; }); return $this; } /** * @param $dir * * @return \Iterator * * @throws \RuntimeException When none of the adapters are supported */ private function searchInDirectory($dir) { if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { $this->exclude = array_merge($this->exclude, self::$vcsPatterns); } if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { $this->notPaths[] = '#(^|/)\..+(/|$)#'; } foreach ($this->adapters as $adapter) { if ($adapter['adapter']->isSupported()) { try { return $this ->buildAdapter($adapter['adapter']) ->searchInDirectory($dir); } catch (ExceptionInterface $e) {} } } throw new \RuntimeException('No supported adapter found.'); } /** * @param AdapterInterface $adapter * * @return AdapterInterface */ private function buildAdapter(AdapterInterface $adapter) { return $adapter ->setFollowLinks($this->followLinks) ->setDepths($this->depths) ->setMode($this->mode) ->setExclude($this->exclude) ->setNames($this->names) ->setNotNames($this->notNames) ->setContains($this->contains) ->setNotContains($this->notContains) ->setSizes($this->sizes) ->setDates($this->dates) ->setFilters($this->filters) ->setSort($this->sort) ->setPath($this->paths) ->setNotPath($this->notPaths) ->ignoreUnreadableDirs($this->ignoreUnreadableDirs); } /** * Unselects all adapters. */ private function resetAdapterSelection() { $this->adapters = array_map(function (array $properties) { $properties['selected'] = false; return $properties; }, $this->adapters); } } PK]d2Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * ExcludeDirectoryFilterIterator filters out directories. * * @author Fabien Potencier */ class ExcludeDirectoryFilterIterator extends FilterIterator { private $patterns = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $directories An array of directories to exclude */ public function __construct(\Iterator $iterator, array $directories) { foreach ($directories as $directory) { $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#'; } parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); $path = strtr($path, '\\', '/'); foreach ($this->patterns as $pattern) { if (preg_match($pattern, $path)) { return false; } } return true; } } PK]xP+Finder/Iterator/SizeRangeFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Comparator\NumberComparator; /** * SizeRangeFilterIterator filters out files that are not in the given size range. * * @author Fabien Potencier */ class SizeRangeFilterIterator extends FilterIterator { private $comparators = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param NumberComparator[] $comparators An array of NumberComparator instances */ public function __construct(\Iterator $iterator, array $comparators) { $this->comparators = $comparators; parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (!$fileinfo->isFile()) { return true; } $filesize = $fileinfo->getSize(); foreach ($this->comparators as $compare) { if (!$compare->test($filesize)) { return false; } } return true; } } PK]n bb*Finder/Iterator/FileTypeFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * FileTypeFilterIterator only keeps files, directories, or both. * * @author Fabien Potencier */ class FileTypeFilterIterator extends FilterIterator { const ONLY_FILES = 1; const ONLY_DIRECTORIES = 2; private $mode; /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param integer $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) */ public function __construct(\Iterator $iterator, $mode) { $this->mode = $mode; parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) { return false; } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) { return false; } return true; } } PK]6s .Finder/Iterator/RecursiveDirectoryIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Exception\AccessDeniedException; use Symfony\Component\Finder\SplFileInfo; /** * Extends the \RecursiveDirectoryIterator to support relative paths * * @author Victor Berchet */ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator { /** * @var boolean */ private $ignoreUnreadableDirs; /** * @var Boolean */ private $rewindable; /** * Constructor. * * @param string $path * @param int $flags * @param boolean $ignoreUnreadableDirs * * @throws \RuntimeException */ public function __construct($path, $flags, $ignoreUnreadableDirs = false) { if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { throw new \RuntimeException('This iterator only support returning current as fileinfo.'); } parent::__construct($path, $flags); $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; } /** * Return an instance of SplFileInfo with support for relative paths * * @return SplFileInfo File information */ public function current() { return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname()); } /** * @return \RecursiveIterator * * @throws AccessDeniedException */ public function getChildren() { try { return parent::getChildren(); } catch (\UnexpectedValueException $e) { if ($this->ignoreUnreadableDirs) { // If directory is unreadable and finder is set to ignore it, a fake empty content is returned. return new \RecursiveArrayIterator(array()); } else { throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); } } } /** * Do nothing for non rewindable stream */ public function rewind() { if (false === $this->isRewindable()) { return; } // @see https://bugs.php.net/bug.php?id=49104 parent::next(); parent::rewind(); } /** * Checks if the stream is rewindable. * * @return Boolean true when the stream is rewindable, false otherwise */ public function isRewindable() { if (null !== $this->rewindable) { return $this->rewindable; } if (false !== $stream = @opendir($this->getPath())) { $infos = stream_get_meta_data($stream); closedir($stream); if ($infos['seekable']) { return $this->rewindable = true; } } return $this->rewindable = false; } } PK]z"(Finder/Iterator/CustomFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * CustomFilterIterator filters files by applying anonymous functions. * * The anonymous function receives a \SplFileInfo and must return false * to remove files. * * @author Fabien Potencier */ class CustomFilterIterator extends FilterIterator { private $filters = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $filters An array of PHP callbacks * * @throws \InvalidArgumentException */ public function __construct(\Iterator $iterator, array $filters) { foreach ($filters as $filter) { if (!is_callable($filter)) { throw new \InvalidArgumentException('Invalid PHP callback.'); } } $this->filters = $filters; parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); foreach ($this->filters as $filter) { if (false === call_user_func($filter, $fileinfo)) { return false; } } return true; } } PK] U+Finder/Iterator/DateRangeFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Comparator\DateComparator; /** * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates). * * @author Fabien Potencier */ class DateRangeFilterIterator extends FilterIterator { private $comparators = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param DateComparator[] $comparators An array of DateComparator instances */ public function __construct(\Iterator $iterator, array $comparators) { $this->comparators = $comparators; parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (!$fileinfo->isFile()) { return true; } $filedate = $fileinfo->getMTime(); foreach ($this->comparators as $compare) { if (!$compare->test($filedate)) { return false; } } return true; } } PK]j $Finder/Iterator/SortableIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * SortableIterator applies a sort on a given Iterator. * * @author Fabien Potencier */ class SortableIterator implements \IteratorAggregate { const SORT_BY_NAME = 1; const SORT_BY_TYPE = 2; const SORT_BY_ACCESSED_TIME = 3; const SORT_BY_CHANGED_TIME = 4; const SORT_BY_MODIFIED_TIME = 5; private $iterator; private $sort; /** * Constructor. * * @param \Traversable $iterator The Iterator to filter * @param integer|callback $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) * * @throws \InvalidArgumentException */ public function __construct(\Traversable $iterator, $sort) { $this->iterator = $iterator; if (self::SORT_BY_NAME === $sort) { $this->sort = function ($a, $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }; } elseif (self::SORT_BY_TYPE === $sort) { $this->sort = function ($a, $b) { if ($a->isDir() && $b->isFile()) { return -1; } elseif ($a->isFile() && $b->isDir()) { return 1; } return strcmp($a->getRealpath(), $b->getRealpath()); }; } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getATime() > $b->getATime()); }; } elseif (self::SORT_BY_CHANGED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getCTime() > $b->getCTime()); }; } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getMTime() > $b->getMTime()); }; } elseif (is_callable($sort)) { $this->sort = $sort; } else { throw new \InvalidArgumentException('The SortableIterator takes a PHP callback or a valid built-in sort algorithm as an argument.'); } } public function getIterator() { $array = iterator_to_array($this->iterator, true); uasort($array, $this->sort); return new \ArrayIterator($array); } } PK] .Finder/Iterator/MultiplePcreFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Expression\Expression; /** * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings). * * @author Fabien Potencier */ abstract class MultiplePcreFilterIterator extends FilterIterator { protected $matchRegexps = array(); protected $noMatchRegexps = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $matchPatterns An array of patterns that need to match * @param array $noMatchPatterns An array of patterns that need to not match */ public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) { foreach ($matchPatterns as $pattern) { $this->matchRegexps[] = $this->toRegex($pattern); } foreach ($noMatchPatterns as $pattern) { $this->noMatchRegexps[] = $this->toRegex($pattern); } parent::__construct($iterator); } /** * Checks whether the string is a regex. * * @param string $str * * @return Boolean Whether the given string is a regex */ protected function isRegex($str) { return Expression::create($str)->isRegex(); } /** * Converts string into regexp. * * @param string $str Pattern * * @return string regexp corresponding to a given string */ abstract protected function toRegex($str); } PK]{^ǽ*Finder/Iterator/FilenameFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Expression\Expression; /** * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string). * * @author Fabien Potencier */ class FilenameFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $filename = $this->current()->getFilename(); // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $filename)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $filename)) { return true; } } } return $match; } /** * Converts glob to regexp. * * PCRE patterns are left unchanged. * Glob strings are transformed with Glob::toRegex(). * * @param string $str Pattern: glob or regexp * * @return string regexp corresponding to a given glob or regexp */ protected function toRegex($str) { return Expression::create($str)->getRegex()->render(); } } PK],G"Finder/Iterator/FilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * This iterator just overrides the rewind method in order to correct a PHP bug. * * @see https://bugs.php.net/bug.php?id=49104 * * @author Alex Bogomazov */ abstract class FilterIterator extends \FilterIterator { /** * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after * rewind in some cases. * * @see FilterIterator::rewind() */ public function rewind() { $iterator = $this; while ($iterator instanceof \OuterIterator) { $innerIterator = $iterator->getInnerIterator(); if ($innerIterator instanceof RecursiveDirectoryIterator) { if ($innerIterator->isRewindable()) { $innerIterator->next(); $innerIterator->rewind(); } } elseif ($iterator->getInnerIterator() instanceof \FilesystemIterator) { $iterator->getInnerIterator()->next(); $iterator->getInnerIterator()->rewind(); } $iterator = $iterator->getInnerIterator(); } parent::rewind(); } } PK])&Finder/Iterator/PathFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * PathFilterIterator filters files by path patterns (e.g. some/special/dir). * * @author Fabien Potencier * @author Włodzimierz Gajda */ class PathFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $filename = $this->current()->getRelativePathname(); if (defined('PHP_WINDOWS_VERSION_MAJOR')) { $filename = strtr($filename, '\\', '/'); } // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $filename)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $filename)) { return true; } } } return $match; } /** * Converts strings to regexp. * * PCRE patterns are left unchanged. * * Default conversion: * 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/' * * Use only / as directory separator (on Windows also). * * @param string $str Pattern: regexp or dirname. * * @return string regexp corresponding to a given string or regexp */ protected function toRegex($str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } } PK]ɔ %Finder/Iterator/FilePathsIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\SplFileInfo; /** * Iterate over shell command result. * * @author Jean-François Simon */ class FilePathsIterator extends \ArrayIterator { /** * @var string */ private $baseDir; /** * @var int */ private $baseDirLength; /** * @var string */ private $subPath; /** * @var string */ private $subPathname; /** * @var SplFileInfo */ private $current; /** * @param array $paths List of paths returned by shell command * @param string $baseDir Base dir for relative path building */ public function __construct(array $paths, $baseDir) { $this->baseDir = $baseDir; $this->baseDirLength = strlen($baseDir); parent::__construct($paths); } /** * @param string $name * @param array $arguments * * @return mixed */ public function __call($name, array $arguments) { return call_user_func_array(array($this->current(), $name), $arguments); } /** * Return an instance of SplFileInfo with support for relative paths. * * @return SplFileInfo File information */ public function current() { return $this->current; } /** * @return string */ public function key() { return $this->current->getPathname(); } public function next() { parent::next(); $this->buildProperties(); } public function rewind() { parent::rewind(); $this->buildProperties(); } /** * @return string */ public function getSubPath() { return $this->subPath; } /** * @return string */ public function getSubPathname() { return $this->subPathname; } private function buildProperties() { $absolutePath = parent::current(); if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) { $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\'); $dir = dirname($this->subPathname); $this->subPath = '.' === $dir ? '' : $dir; } else { $this->subPath = $this->subPathname = ''; } $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname); } } PK]ʽ-Finder/Iterator/FilecontentFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings). * * @author Fabien Potencier * @author Włodzimierz Gajda */ class FilecontentFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { if (!$this->matchRegexps && !$this->noMatchRegexps) { return true; } $fileinfo = $this->current(); if ($fileinfo->isDir() || !$fileinfo->isReadable()) { return false; } $content = $fileinfo->getContents(); if (!$content) { return false; } // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $content)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $content)) { return true; } } } return $match; } /** * Converts string to regexp if necessary. * * @param string $str Pattern: string or regexp * * @return string regexp corresponding to a given string or regexp */ protected function toRegex($str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } } PK]ils_,Finder/Iterator/DepthRangeFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * DepthRangeFilterIterator limits the directory depth. * * @author Fabien Potencier */ class DepthRangeFilterIterator extends FilterIterator { private $minDepth = 0; /** * Constructor. * * @param \RecursiveIteratorIterator $iterator The Iterator to filter * @param int $minDepth The min depth * @param int $maxDepth The max depth */ public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX) { $this->minDepth = $minDepth; $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { return $this->getInnerIterator()->getDepth() >= $this->minDepth; } } PK]%uMPPFinder/autoloader.phpnu[!Templating/Loader/ChainLoader.phpnu[PK]I<h HttpKernel/Log/NullLogger.phpnu[PK]J=[['HttpKernel/Log/DebugLoggerInterface.phpnu[PK]~[  "THttpKernel/Log/LoggerInterface.phpnu[PK]=AA"HttpKernel/HttpKernelInterface.phpnu[PK];M,FHttpKernel/DependencyInjection/Extension.phpnu[PK]&!#ffB"HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.phpnu[PK]u__8^'HttpKernel/DependencyInjection/ConfigurableExtension.phpnu[PK]k8%-HttpKernel/DependencyInjection/RegisterListenersPass.phpnu[PK]QNR8_=HttpKernel/DependencyInjection/AddClassesToCachePass.phpnu[PK]6V V ;BHttpKernel/DependencyInjection/ContainerAwareHttpKernel.phpnu[PK]Yxځ551cMHttpKernel/CacheClearer/CacheClearerInterface.phpnu[PK]-OHttpKernel/CacheClearer/ChainCacheClearer.phpnu[PK]2~~0THttpKernel/DataCollector/ConfigDataCollector.phpnu[PK](; ; 0mHttpKernel/DataCollector/MemoryDataCollector.phpnu[PK].3NwHttpKernel/DataCollector/DataCollectorInterface.phpnu[PK]@:o o 0{HttpKernel/DataCollector/RouterDataCollector.phpnu[PK] <7HttpKernel/DataCollector/LateDataCollectorInterface.phpnu[PK]޹ 0HttpKernel/DataCollector/LoggerDataCollector.phpnu[PK] /HttpKernel/DataCollector/EventDataCollector.phpnu[PK]83HttpKernel/DataCollector/ExceptionDataCollector.phpnu[PK]ƏGV .HttpKernel/DataCollector/TimeDataCollector.phpnu[PK] +66/HttpKernel/DataCollector/Util/ValueExporter.phpnu[PK]n--*HttpKernel/DataCollector/DataCollector.phpnu[PK]IYz((1HttpKernel/DataCollector/RequestDataCollector.phpnu[PK]^FF,`HttpKernel/CacheWarmer/WarmableInterface.phpnu[PK]8ee&HttpKernel/CacheWarmer/CacheWarmer.phpnu[PK]R!MM/HttpKernel/CacheWarmer/CacheWarmerAggregate.phpnu[PK]_S77/iHttpKernel/CacheWarmer/CacheWarmerInterface.phpnu[PK]\[HttpKernel/KernelInterface.phpnu[PK]?.\\ HttpKernel/Kernel.phpnu[PK]d! lHttpKernel/Config/FileLocator.phpnu[PK]JzrHttpKernel/UriSigner.phpnu[PK]qK-##.xHttpKernel/Fragment/InlineFragmentRenderer.phpnu[PK]m3 3 0yHttpKernel/Fragment/RoutableFragmentRenderer.phpnu[PK]jg + HttpKernel/Fragment/EsiFragmentRenderer.phpnu[PK]R'UHttpKernel/Fragment/FragmentHandler.phpnu[PK]5앾08HttpKernel/Fragment/HIncludeFragmentRenderer.phpnu[PK]z1MHttpKernel/Fragment/FragmentRendererInterface.phpnu[PK] KK!HttpKernel/Debug/ErrorHandler.phpnu[PK]eڮ55-!HttpKernel/Debug/TraceableEventDispatcher.phpnu[PK]9% HttpKernel/Debug/ExceptionHandler.phpnu[PK]N#FF`HttpKernel/Client.phpnu[PK]iY~2 2 /*HttpKernel/Profiler/MemcacheProfilerStorage.phpnu[PK]\Y`+|5HttpKernel/Profiler/FileProfilerStorage.phpnu[PK]rLU0SHttpKernel/Profiler/ProfilerStorageInterface.phpnu[PK]t}[-YHttpKernel/Profiler/SqliteProfilerStorage.phpnu[PK]TsX X ,mHttpKernel/Profiler/MysqlProfilerStorage.phpnu[PK]N'',vHttpKernel/Profiler/RedisProfilerStorage.phpnu[PK]$ 0HttpKernel/Profiler/MemcachedProfilerStorage.phpnu[PK]   HttpKernel/Profiler/Profiler.phpnu[PK]BWzll.QHttpKernel/Profiler/MongoDbProfilerStorage.phpnu[PK] HttpKernel/Profiler/Profile.phpnu[PK]*#HttpKernel/Profiler/PdoProfilerStorage.phpnu[PK]t3HttpKernel/Profiler/BaseMemcacheProfilerStorage.phpnu[PK]٨.kk8r4HttpKernel/Event/GetResponseForControllerResultEvent.phpnu[PK]91E;HttpKernel/Event/GetResponseForExceptionEvent.phpnu[PK]% *zBHttpKernel/Event/FilterControllerEvent.phpnu[PK],&&&LHttpKernel/Event/PostResponseEvent.phpnu[PK]}x SHttpKernel/Event/KernelEvent.phpnu[PK] 7';\HttpKernel/Event/FinishRequestEvent.phpnu[PK]9I%Q^HttpKernel/Event/GetResponseEvent.phpnu[PK]`g(1dHttpKernel/Event/FilterResponseEvent.phpnu[PK]ST)JjHttpKernel/Exception/FlattenException.phpnu[PK]+;XX8mHttpKernel/Exception/ServiceUnavailableHttpException.phpnu[PK];COO8ArHttpKernel/Exception/PreconditionFailedHttpException.phpnu[PK]+~~:uHttpKernel/Exception/PreconditionRequiredHttpException.phpnu[PK]C%؝SS:yHttpKernel/Exception/UnsupportedMediaTypeHttpException.phpnu[PK]<~6}HttpKernel/Exception/MethodNotAllowedHttpException.phpnu[PK])8*uu2HttpKernel/Exception/AccessDeniedHttpException.phpnu[PK]^,HttpKernel/Exception/FatalErrorException.phpnu[PK]EE3HttpKernel/Exception/NotAcceptableHttpException.phpnu[PK]瞻??.?HttpKernel/Exception/NotFoundHttpException.phpnu[PK][G??0܏HttpKernel/Exception/BadRequestHttpException.phpnu[PK]rQrW/{HttpKernel/Exception/HttpExceptionInterface.phpnu[PK]*2HttpKernel/Exception/UnauthorizedHttpException.phpnu[PK]N0;;.ƚHttpKernel/Exception/ConflictHttpException.phpnu[PK] GG4_HttpKernel/Exception/LengthRequiredHttpException.phpnu[PK]Ѕ33* HttpKernel/Exception/GoneHttpException.phpnu[PK]75HttpKernel/Exception/TooManyRequestsHttpException.phpnu[PK]W1d&HttpKernel/Exception/HttpException.phpnu[PK] -|HttpKernel/EventListener/FragmentListener.phpnu[PK]S "P P +bHttpKernel/EventListener/LocaleListener.phpnu[PK]$$5 HttpKernel/EventListener/StreamedResponseListener.phpnu[PK] .HttpKernel/EventListener/ExceptionListener.phpnu[PK]PCyy-HttpKernel/EventListener/ResponseListener.phpnu[PK] --+HttpKernel/EventListener/RouterListener.phpnu[PK]E^-6HttpKernel/EventListener/ProfilerListener.phpnu[PK]/)A A 0HttpKernel/EventListener/TestSessionListener.phpnu[PK]@S,!HttpKernel/EventListener/SessionListener.phpnu[PK]|$1'HttpKernel/EventListener/ErrorsLoggerListener.phpnu[PK]^(,HttpKernel/EventListener/EsiListener.phpnu[PK]3a%2HttpKernel/Bundle/BundleInterface.phpnu[PK]!ll<HttpKernel/Bundle/Bundle.phpnu[PK]b b 'QHttpKernel/HttpCache/StoreInterface.phpnu[PK]/) 1\HttpKernel/HttpCache/EsiResponseCacheStrategy.phpnu[PK]#[["fHttpKernel/HttpCache/HttpCache.phpnu[PK]K:11HttpKernel/HttpCache/Store.phpnu[PK]wn n HttpKernel/HttpCache/Esi.phpnu[PK]M~CC:HttpKernel/HttpCache/EsiResponseCacheStrategyInterface.phpnu[PK]xXX-HttpKernel/Controller/ControllerReference.phpnu[PK]^/|Goo59 HttpKernel/Controller/ControllerResolverInterface.phpnu[PK]|  5 (HttpKernel/Controller/TraceableControllerResolver.phpnu[PK]NCtt,~.HttpKernel/Controller/ControllerResolver.phpnu[PK]z TTNBHttpKernel/autoloader.phpnu[PK]^R<<COptionsResolver/Options.phpnu[PK]G,ŀOptionsResolver/OptionsResolverInterface.phpnu[PK]}8%8%#OptionsResolver/OptionsResolver.phpnu[PK]E@^0OptionsResolver/Exception/ExceptionInterface.phpnu[PK]sZ5OptionsResolver/Exception/InvalidOptionsException.phpnu[PK]yPH7OptionsResolver/Exception/OptionDefinitionException.phpnu[PK] p5oOptionsResolver/Exception/MissingOptionsException.phpnu[PK]]='YYOptionsResolver/autoloader.phpnu[PK];xDependencyInjection/LazyProxy/PhpDumper/DumperInterface.phpnu[PK]ҳ6DependencyInjection/LazyProxy/PhpDumper/NullDumper.phpnu[PK]innFDependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.phpnu[PK]JJDDependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.phpnu[PK]0DependencyInjection/TaggedContainerInterface.phpnu[PK]EBEB!DependencyInjection/Container.phpnu[PK]CoMM;(DependencyInjection/Extension/PrependExtensionInterface.phpnu[PK]o +U+DependencyInjection/Extension/Extension.phpnu[PK]DS4:DependencyInjection/Extension/ExtensionInterface.phpnu[PK]JA'ADependencyInjection/Extension/ConfigurationExtensionInterface.phpnu[PK];Yޯ*|EDependencyInjection/ExpressionLanguage.phpnu[PK]l5JDependencyInjection/Alias.phpnu[PK]**(ODependencyInjection/Dumper/XmlDumper.phpnu[PK]"^ (zDependencyInjection/Dumper/PhpDumper.phpnu[PK]}.I' DependencyInjection/Dumper/DumperInterface.phpnu[PK]N/++%* DependencyInjection/Dumper/Dumper.phpnu[PK]%%-. DependencyInjection/Dumper/GraphvizDumper.phpnu[PK]A:$:$)\T DependencyInjection/Dumper/YamlDumper.phpnu[PK]$77 x DependencyInjection/Variable.phpnu[PK]E?*v| DependencyInjection/ContainerInterface.phpnu[PK]] I I ( DependencyInjection/SimpleXMLElement.phpnu[PK]U穌PP+ DependencyInjection/DefinitionDecorator.phpnu[PK]LFFC. DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.phpnu[PK][ : DependencyInjection/Compiler/ServiceReferenceGraphNode.phpnu[PK]dd<B DependencyInjection/Compiler/CheckDefinitionValidityPass.phpnu[PK]iJT = DependencyInjection/Compiler/ResolveInvalidReferencesPass.phpnu[PK]X\\@+ DependencyInjection/Compiler/MergeExtensionConfigurationPass.phpnu[PK]V%) ) 6 DependencyInjection/Compiler/ServiceReferenceGraph.phpnu[PK]!?9 DependencyInjection/Compiler/RemovePrivateAliasesPass.phpnu[PK]Eų8 DependencyInjection/Compiler/RepeatablePassInterface.phpnu[PK]nnA DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.phpnu[PK]b[_66M DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.phpnu[PK]Gp5 5 ) DependencyInjection/Compiler/Compiler.phpnu[PK]C\Z+ DependencyInjection/Compiler/PassConfig.phpnu[PK]ϒ?4 DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.phpnu[PK]iZ <-J DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.phpnu[PK]1mU DependencyInjection/Compiler/LoggingFormatter.phpnu[PK]U*''>[ DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.phpnu[PK]0є##-` DependencyInjection/Compiler/RepeatedPass.phpnu[PK]_96h DependencyInjection/Compiler/CompilerPassInterface.phpnu[PK]@ q q <k DependencyInjection/Compiler/CheckCircularReferencesPass.phpnu[PK]ۻǠ=u DependencyInjection/Compiler/AnalyzeServiceReferencesPass.phpnu[PK] ;ه DependencyInjection/Compiler/CheckReferenceValidityPass.phpnu[PK]P P ?F DependencyInjection/Compiler/ResolveReferencesToAliasesPass.phpnu[PK]m= DependencyInjection/Compiler/InlineServiceDefinitionsPass.phpnu[PK]x7:b DependencyInjection/Compiler/ServiceReferenceGraphEdge.phpnu[PK]F"! DependencyInjection/Parameter.phpnu[PK]BtBB8 DependencyInjection/IntrospectableContainerInterface.phpnu[PK]ӸBj, DependencyInjection/Loader/IniFileLoader.phpnu[PK]!+++-. DependencyInjection/Loader/YamlFileLoader.phpnu[PK]z#a?% DependencyInjection/Loader/schema/dic/services/services-1.0.xsdnu[PK]Ua--) DependencyInjection/Loader/FileLoader.phpnu[PK] ,( DependencyInjection/Loader/ClosureLoader.phpnu[PK]L88,u% DependencyInjection/Loader/XmlFileLoader.phpnu[PK]((,^ DependencyInjection/Loader/PhpFileLoader.phpnu[PK]l.06e DependencyInjection/Exception/LogicException.phpnu[PK]94Rg DependencyInjection/Exception/ExceptionInterface.phpnu[PK] +2i DependencyInjection/Exception/RuntimeException.phpnu[PK]= ԥAl DependencyInjection/Exception/ScopeCrossingInjectionException.phpnu[PK] O,8+t DependencyInjection/Exception/BadMethodCallException.phpnu[PK]]Cgv DependencyInjection/Exception/ServiceCircularReferenceException.phpnu[PK]qBEz DependencyInjection/Exception/ParameterCircularReferenceException.phpnu[PK]zA~ DependencyInjection/Exception/ScopeWideningInjectionException.phpnu[PK]\ < DependencyInjection/Exception/ParameterNotFoundException.phpnu[PK] : DependencyInjection/Exception/ServiceNotFoundException.phpnu[PK]I_8? DependencyInjection/Exception/InactiveScopeException.phpnu[PK]: DependencyInjection/Exception/InvalidArgumentException.phpnu[PK]{6 DependencyInjection/Exception/OutOfBoundsException.phpnu[PK]c!8989"L DependencyInjection/Definition.phpnu[PK]ܮP8 : DependencyInjection/ParameterBag/ParameterBagInterface.phpnu[PK]U" " 1 DependencyInjection/ParameterBag/ParameterBag.phpnu[PK]ך7l DependencyInjection/ParameterBag/FrozenParameterBag.phpnu[PK]q8I/ DependencyInjection/ContainerAwareInterface.phpnu[PK]H 8+ DependencyInjection/ContainerAwareTrait.phpnu[PK]uii&J DependencyInjection/ContainerAware.phpnu[PK]-R],,!  DependencyInjection/Reference.phpnu[PK],xmm DependencyInjection/Scope.phpnu[PK]-&(@ DependencyInjection/ContainerBuilder.phpnu[PK]_J& DependencyInjection/ScopeInterface.phpnu[PK] ]]" DependencyInjection/autoloader.phpnu[PK]g?Z < Translation/Interval.phpnu[PK]P?}}(s Translation/Writer/TranslationWriter.phpnu[PK]66%H Translation/Dumper/YamlFileDumper.phpnu[PK]oB$ӽ Translation/Dumper/CsvFileDumper.phpnu[PK]:$}}% Translation/Dumper/JsonFileDumper.phpnu[PK]<̧& Translation/Dumper/XliffFileDumper.phpnu[PK]<**& Translation/Dumper/DumperInterface.phpnu[PK]%LL$T Translation/Dumper/PhpFileDumper.phpnu[PK]ਪ(# Translation/Dumper/PoFileDumper.phpnu[PK]M 'I Translation/Dumper/IcuResFileDumper.phpnu[PK]A A #1 Translation/Dumper/MoFileDumper.phpnu[PK]&X$ Translation/Dumper/IniFileDumper.phpnu[PK]B^[[! Translation/Dumper/FileDumper.phpnu[PK]>{GG# Translation/Dumper/QtFileDumper.phpnu[PK]b*0oo"7 Translation/PluralizationRules.phpnu[PK]N@ $ Translation/Loader/IniFileLoader.phpnu[PK])-d+ #9% Translation/Loader/QtFileLoader.phpnu[PK]:%/ Translation/Loader/YamlFileLoader.phpnu[PK]v#7 Translation/Loader/MoFileLoader.phpnu[PK]: Z""0N Translation/Loader/schema/dic/xliff-core/xml.xsdnu[PK]xOBq Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu[PK]'su u %@Translation/Loader/JsonFileLoader.phpnu[PK]TÏ' Translation/Loader/IcuDatFileLoader.phpnu[PK]CSz z 'Translation/Loader/IcuResFileLoader.phpnu[PK]l#tt&!Translation/Loader/LoaderInterface.phpnu[PK]r;;$&Translation/Loader/PhpFileLoader.phpnu[PK]R",Translation/Loader/ArrayLoader.phpnu[PK]*#4Translation/Loader/PoFileLoader.phpnu[PK]i3" " $ULTranslation/Loader/CsvFileLoader.phpnu[PK]_BB&VTranslation/Loader/XliffFileLoader.phpnu[PK]d<<"ckTranslation/IdentityTranslator.phpnu[PK]6",qTranslation/Exception/ExceptionInterface.phpnu[PK]DŽ2tTranslation/Exception/InvalidResourceException.phpnu[PK]2B3tvTranslation/Exception/NotFoundResourceException.phpnu[PK]%Mt&xTranslation/MetadataAwareInterface.phpnu[PK]y4 3Translation/MessageCatalogue.phpnu[PK]֛)Translation/MessageCatalogueInterface.phpnu[PK]Locale/Stub/DateFormat/DayOfYearTransformer.phpnu[PK] 9u.ALocale/Stub/DateFormat/Hour1200Transformer.phpnu[PK]k&"M.oELocale/Stub/DateFormat/Hour1201Transformer.phpnu[PK]S.HLocale/Stub/DateFormat/TimeZoneTransformer.phpnu[PK]tz  +cLLocale/Stub/DateFormat/MonthTransformer.phpnu[PK].OLocale/Stub/DateFormat/Hour2400Transformer.phpnu[PK]X*BSLocale/Stub/DateFormat/AmPmTransformer.phpnu[PK]&#VLocale/Stub/StubNumberFormatter.phpnu[PK]CYLocale/Stub/StubIntl.phpnu[PK]?\Locale/Stub/StubCollator.phpnu[PK]q*( ( \_Locale/Stub/StubLocale.phpnu[PK]FPPPjLocale/autoloader.phpnu[PK]3{+clFilesystem/Exception/ExceptionInterface.phpnu[PK];{$nFilesystem/Exception/IOException.phpnu[PK]dP.rFilesystem/Exception/FileNotFoundException.phpnu[PK]oC~-vFilesystem/Exception/IOExceptionInterface.phpnu[PK]tTTyFilesystem/autoloader.phpnu[PK]OظGG={Filesystem/Filesystem.phpnu[PK]I Config/FileLocator.phpnu[PK]C3kllConfig/FileLocatorInterface.phpnu[PK]kConfig/Util/XmlUtils.phpnu[PK]B""Config/Definition/BaseNode.phpnu[PK]eww,+Config/Definition/PrototypeNodeInterface.phpnu[PK]jkk!Config/Definition/IntegerNode.phpnu[PK]+;; Config/Definition/ScalarNode.phpnu[PK]m+EConfig/Definition/FloatNode.phpnu[PK]*dd,"Config/Definition/ConfigurationInterface.phpnu[PK]Un=#'#')E%Config/Definition/PrototypedArrayNode.phpnu[PK]2&&/LConfig/Definition/Dumper/XmlReferenceDumper.phpnu[PK]i >>0sConfig/Definition/Dumper/YamlReferenceDumper.phpnu[PK]G4**DConfig/Definition/ArrayNode.phpnu[PK]!zConfig/Definition/BooleanNode.phpnu[PK] })vConfig/Definition/Builder/NodeBuilder.phpnu[PK]881Config/Definition/Builder/ArrayNodeDefinition.phpnu[PK]{{* Config/Definition/Builder/MergeBuilder.phpnu[PK]# ֕442Config/Definition/Builder/NormalizationBuilder.phpnu[PK]'nڭ3EConfig/Definition/Builder/IntegerNodeDefinition.phpnu[PK]mc2Config/Definition/Builder/ScalarNodeDefinition.phpnu[PK]~GXX3Config/Definition/Builder/NumericNodeDefinition.phpnu[PK]U=1%Config/Definition/Builder/NodeParentInterface.phpnu[PK]e@4'Config/Definition/Builder/VariableNodeDefinition.phpnu[PK]VhU).Config/Definition/Builder/TreeBuilder.phpnu[PK]tp15Config/Definition/Builder/FloatNodeDefinition.phpnu[PK] "$$)8Config/Definition/Builder/ExprBuilder.phpnu[PK]ʍ0fMConfig/Definition/Builder/EnumNodeDefinition.phpnu[PK],l[[/}RConfig/Definition/Builder/ValidationBuilder.phpnu[PK]K,7WConfig/Definition/Builder/NodeDefinition.phpnu[PK]P3tConfig/Definition/Builder/BooleanNodeDefinition.phpnu[PK]3d__;xConfig/Definition/Builder/ParentNodeDefinitionInterface.phpnu[PK]]F4:a{Config/Definition/Exception/InvalidDefinitionException.phpnu[PK]|EE5}Config/Definition/Exception/DuplicateKeyException.phpnu[PK]@4OConfig/Definition/Exception/InvalidTypeException.phpnu[PK]1Config/Definition/Exception/UnsetKeyException.phpnu[PK]5-=Config/Definition/Exception/InvalidConfigurationException.phpnu[PK]C)AConfig/Definition/Exception/Exception.phpnu[PK]:2&QQ;dConfig/Definition/Exception/ForbiddenOverwriteException.phpnu[PK]-*ҹ--! Config/Definition/NumericNode.phpnu[PK]$¸ "Config/Definition/VariableNode.phpnu[PK]aVp  Config/Definition/EnumNode.phpnu[PK]U' ' Config/Definition/Processor.phpnu[PK]fJ#xConfig/Definition/NodeInterface.phpnu[PK]000%TConfig/Definition/ReferenceDumper.phpnu[PK]=ٹConfig/Loader/Loader.phpnu[PK])Config/Loader/LoaderResolverInterface.phpnu[PK]__wP< < #Config/Loader/FileLoader.phpnu[PK]499!Config/Loader/LoaderInterface.phpnu[PK]HPʉ 5Config/Loader/LoaderResolver.phpnu[PK]))"Config/Loader/DelegatingLoader.phpnu[PK]W ,Config/Exception/FileLoaderLoadException.phpnu[PK]7 TT?Config/Exception/FileLoaderImportCircularReferenceException.phpnu[PK]fKEDD%Config/Resource/ResourceInterface.phpnu[PK] # %6Config/Resource/DirectoryResource.phpnu[PK]T!! \Config/Resource/FileResource.phpnu[PK]:a  Config/ConfigCache.phpnu[PK]`PP Config/autoloader.phpnu[PK]O#ClassLoader/WinCacheClassLoader.phpnu[PK]S  'ClassLoader/DebugClassLoader.phpnu[PK]AS5ClassLoader/MapClassLoader.phpnu[PK]a ';ClassLoader/ApcUniversalClassLoader.phpnu[PK]a.e"e"$GClassLoader/UniversalClassLoader.phpnu[PK]?wy !jClassLoader/ClassMapGenerator.phpnu[PK]v . .%xClassLoader/ClassCollectionLoader.phpnu[PK]lOݫ"ClassLoader/ApcClassLoader.phpnu[PK]PЩ !ClassLoader/XcacheClassLoader.phpnu[PK]w!)))ClassLoader/DebugUniversalClassLoader.phpnu[PK]v'ClassLoader/ClassLoader.phpnu[PK]"KUUdClassLoader/autoloader.phpnu[PK]Sf Form/PreloadedExtension.phpnu[PK]*[Form/ResolvedFormType.phpnu[PK]xfh..$ Form/Resources/config/validation.xmlnu[PK]-- Form/Resources/translations/validators.ru.xlfnu[PK] -Form/Resources/translations/validators.pt.xlfnu[PK]n-$Form/Resources/translations/validators.en.xlfnu[PK]NP\-)Form/Resources/translations/validators.he.xlfnu[PK]-Form/Resources/translations/validators.mn.xlfnu[PK]:-"Form/Resources/translations/validators.pl.xlfnu[PK]5-&Form/Resources/translations/validators.sl.xlfnu[PK]_Π-*Form/Resources/translations/validators.el.xlfnu[PK]X-/Form/Resources/translations/validators.da.xlfnu[PK]-r3Form/Resources/translations/validators.fi.xlfnu[PK]4@07Form/Resources/translations/validators.pt_BR.xlfnu[PK]Hq-;Form/Resources/translations/validators.lt.xlfnu[PK]O-?Form/Resources/translations/validators.nl.xlfnu[PK]s>ll-CForm/Resources/translations/validators.sv.xlfnu[PK]A4-GForm/Resources/translations/validators.gl.xlfnu[PK]y99-KForm/Resources/translations/validators.hy.xlfnu[PK]TI-yPForm/Resources/translations/validators.de.xlfnu[PK]誫-TForm/Resources/translations/validators.sk.xlfnu[PK]%-XForm/Resources/translations/validators.lv.xlfnu[PK] -#]Form/Resources/translations/validators.cs.xlfnu[PK]WgUugg-5aForm/Resources/translations/validators.nb.xlfnu[PK]8,:0dForm/Resources/translations/validators.zh_CN.xlfnu[PK] b8-hForm/Resources/translations/validators.hr.xlfnu[PK]be@-lForm/Resources/translations/validators.hu.xlfnu[PK]္o332 qForm/Resources/translations/validators.sr_Cyrl.xlfnu[PK]-uForm/Resources/translations/validators.ja.xlfnu[PK]|C-yForm/Resources/translations/validators.ar.xlfnu[PK]*{-X~Form/Resources/translations/validators.lb.xlfnu[PK]0h-Form/Resources/translations/validators.es.xlfnu[PK]Ed-Form/Resources/translations/validators.ro.xlfnu[PK]<yy-&Form/Resources/translations/validators.uk.xlfnu[PK]_8-Form/Resources/translations/validators.fr.xlfnu[PK]!aZ-0Form/Resources/translations/validators.it.xlfnu[PK] !-FForm/Resources/translations/validators.ca.xlfnu[PK]3Ե^^-iForm/Resources/translations/validators.bg.xlfnu[PK]ٻ||-$Form/Resources/translations/validators.eu.xlfnu[PK]q-Form/Resources/translations/validators.id.xlfnu[PK]S*-Form/Resources/translations/validators.et.xlfnu[PK]V5-%Form/Resources/translations/validators.fa.xlfnu[PK]r2Form/Resources/translations/validators.sr_Latn.xlfnu[PK]&"̰TTForm/FormConfigBuilder.phpnu[PK]s  Form/FormInterface.phpnu[PK]dx+Form/FormRegistry.phpnu[PK]a(0kkN>Form/Test/FormInterface.phpnu[PK]myy"@Form/Test/FormBuilderInterface.phpnu[PK]sŪAForm/Test/TypeTestCase.phpnu[PK]B4I++%!FForm/Test/FormIntegrationTestCase.phpnu[PK],7//%IForm/Test/DeprecationErrorHandler.phpnu[PK]+qDAA%%NForm/Test/FormPerformanceTestCase.phpnu[PK] TForm/NativeRequestHandler.phpnu[PK] f2jForm/Extension/Csrf/Type/FormTypeCsrfExtension.phpnu[PK]"q%7Form/Extension/Csrf/CsrfExtension.phpnu[PK]R'WTT<PForm/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu[PK]8Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu[PK]%G:\Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu[PK][^8Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu[PK]C8Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu[PK]?oo<Form/Extension/Csrf/EventListener/CsrfValidationListener.phpnu[PK]զY6Form/Extension/Templating/TemplatingRendererEngine.phpnu[PK],QQ1Form/Extension/Templating/TemplatingExtension.phpnu[PK]uUSW W CForm/Extension/DependencyInjection/DependencyInjectionExtension.phpnu[PK]#117TForm/Extension/DataCollector/DataCollectorExtension.phpnu[PK]1 uu@Form/Extension/DataCollector/Type/DataCollectorTypeExtension.phpnu[PK];Form/Extension/DataCollector/FormDataExtractorInterface.phpnu[PK]| ]E-Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.phpnu[PK]((LcForm/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.phpnu[PK]I2  D Form/Extension/DataCollector/EventListener/DataCollectorListener.phpnu[PK]6s2Form/Extension/DataCollector/FormDataCollector.phpnu[PK]T ;1Form/Extension/DataCollector/FormDataCollectorInterface.phpnu[PK]%`2>Form/Extension/DataCollector/FormDataExtractor.phpnu[PK]j= = >PForm/Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu[PK]PffF@[Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu[PK]䋧 CaForm/Extension/HttpFoundation/EventListener/BindRequestListener.phpnu[PK]Q9'mForm/Extension/HttpFoundation/HttpFoundationExtension.phpnu[PK]  56pForm/Extension/Core/DataMapper/PropertyPathMapper.phpnu[PK]&PP'}Form/Extension/Core/View/ChoiceView.phpnu[PK]uƵ``(QForm/Extension/Core/Type/IntegerType.phpnu[PK]aLŢ( Form/Extension/Core/Type/CountryType.phpnu[PK]DU'Form/Extension/Core/Type/SubmitType.phpnu[PK]8JJ'7Form/Extension/Core/Type/SearchType.phpnu[PK])ؕForm/Extension/Core/Type/LanguageType.phpnu[PK]a&ؙForm/Extension/Core/Type/ResetType.phpnu[PK]Ѝ''Form/Extension/Core/Type/HiddenType.phpnu[PK] &'')Form/Extension/Core/Type/DateTimeType.phpnu[PK]Goo% Form/Extension/Core/Type/FileType.phpnu[PK]HH&Form/Extension/Core/Type/EmailType.phpnu[PK]7pOLL&lForm/Extension/Core/Type/RadioType.phpnu[PK]9)Form/Extension/Core/Type/RepeatedType.phpnu[PK]ٝGG%uForm/Extension/Core/Type/BaseType.phpnu[PK]&ߏvv)Form/Extension/Core/Type/BirthdayType.phpnu[PK]H?!a%Form/Extension/Core/Type/TimeType.phpnu[PK]M2\3,3,%+Form/Extension/Core/Type/DateType.phpnu[PK]옇)=Form/Extension/Core/Type/PasswordType.phpnu[PK]T;%BForm/Extension/Core/Type/TextType.phpnu[PK]q$FForm/Extension/Core/Type/UrlType.phpnu[PK]5S &(KForm/Extension/Core/Type/MoneyType.phpnu[PK]tII) XForm/Extension/Core/Type/TextareaType.phpnu[PK]/++'[Form/Extension/Core/Type/ChoiceType.phpnu[PK]Ci'Form/Extension/Core/Type/NumberType.phpnu[PK]:y  %Form/Extension/Core/Type/FormType.phpnu[PK]h'FForm/Extension/Core/Type/ButtonType.phpnu[PK]񍢸)Form/Extension/Core/Type/CurrencyType.phpnu[PK]Z^^(Form/Extension/Core/Type/PercentType.phpnu[PK]D'RForm/Extension/Core/Type/LocaleType.phpnu[PK]_LL)mForm/Extension/Core/Type/TimezoneType.phpnu[PK]TT)Form/Extension/Core/Type/CheckboxType.phpnu[PK][Gԃ +Form/Extension/Core/Type/CollectionType.phpnu[PK])b""LForm/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu[PK]c8V <eForm/Extension/Core/DataTransformer/DataTransformerChain.phpnu[PK]/C?]Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.phpnu[PK];ddKForm/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu[PK]H  ?Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.phpnu[PK]ggB Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu[PK]  D(Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu[PK]e^  Df2Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu[PK]]yD D I;Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu[PK]'tqk55HEForm/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu[PK]TBTTForm/Extension/Core/DataTransformer/BooleanToStringTransformer.phpnu[PK]Lpx&&G\Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu[PK]Ze  B\lForm/Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu[PK]UdqKچForm/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu[PK]ΎgW C]Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu[PK]O###JRForm/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu[PK]"h@^Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu[PK]Þ F{Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu[PK]'ç??-Form/Extension/Core/ChoiceList/ChoiceList.phpnu[PK] ##3#Form/Extension/Core/ChoiceList/ObjectChoiceList.phpnu[PK]В4 4 1BForm/Extension/Core/ChoiceList/LazyChoiceList.phpnu[PK]jю3OForm/Extension/Core/ChoiceList/SimpleChoiceList.phpnu[PK]l_R(6eForm/Extension/Core/ChoiceList/ChoiceListInterface.phpnu[PK]>Q?<{Form/Extension/Core/EventListener/FixUrlProtocolListener.phpnu[PK]?D; Form/Extension/Core/EventListener/FixRadioInputListener.phpnu[PK]õe=PForm/Extension/Core/EventListener/MergeCollectionListener.phpnu[PK]:AA2OForm/Extension/Core/EventListener/TrimListener.phpnu[PK]b >Form/Extension/Core/EventListener/FixCheckboxInputListener.phpnu[PK]\//8Form/Extension/Core/EventListener/ResizeFormListener.phpnu[PK]CW%Form/Extension/Core/CoreExtension.phpnu[PK]-P6Form/Extension/Validator/Constraints/FormValidator.phpnu[PK]}>ُ-Form/Extension/Validator/Constraints/Form.phpnu[PK]8Form/Extension/Validator/Type/BaseValidatorExtension.phpnu[PK]1>Form/Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu[PK]͚>@@@YForm/Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu[PK]eBR < Form/Extension/Validator/Type/FormTypeValidatorExtension.phpnu[PK]lCt*t*1MForm/Extension/Validator/ValidatorTypeGuesser.phpnu[PK]Ck.")Form/Extension/Validator/Util/ServerParams.phpnu[PK]*= 0Form/Extension/Validator/EventListener/ValidationListener.phpnu[PK]2=[<((/8Form/Extension/Validator/ValidatorExtension.phpnu[PK]-!!:?Form/Extension/Validator/ViolationMapper/ViolationPath.phpnu[PK]f 8YForm/Extension/Validator/ViolationMapper/MappingRule.phpnu[PK]kt==E@dForm/Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu[PK]\T9hForm/Extension/Validator/ViolationMapper/RelativePath.phpnu[PK]ɥSBlForm/Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu[PK]C_hU+U+</pForm/Extension/Validator/ViolationMapper/ViolationMapper.phpnu[PK]E Form/FormRendererInterface.phpnu[PK]:   Form/FormBuilderInterface.phpnu[PK]QTppyForm/SubmitButtonBuilder.phpnu[PK]>*ii5Form/FormFactory.phpnu[PK]ÊM'%%Form/FormConfigInterface.phpnu[PK]ɃT $SForm/FormFactoryBuilderInterface.phpnu[PK](s //Form/ClickableInterface.phpnu[PK] ͋  Form/Forms.phpnu[PK] \ Form/FormTypeInterface.phpnu[PK]F22&<Form/Util/VirtualFormAwareIterator.phpnu[PK]I 66Form/Util/OrderedHashMap.phpnu[PK]y$$F-Form/Util/FormUtil.phpnu[PK]<&1Form/Util/InheritDataAwareIterator.phpnu[PK]h''$4Form/Util/OrderedHashMapIterator.phpnu[PK]|G "mCForm/ResolvedFormTypeInterface.phpnu[PK]nPForm/FormExtensionInterface.phpnu[PK]Wb[H[H}WForm/ButtonBuilder.phpnu[PK]/ttForm/FormEvents.phpnu[PK]  դForm/Guess/TypeGuess.phpnu[PK]R=Form/Guess/ValueGuess.phpnu[PK]51 1 eForm/Guess/Guess.phpnu[PK]pڻForm/AbstractRendererEngine.phpnu[PK]@ @ Form/FormTypeGuesserChain.phpnu[PK]=MM#Form/FormTypeExtensionInterface.phpnu[PK]0\ZZ(Form/CallbackTransformer.phpnu[PK]?zz!Form/FormTypeGuesserInterface.phpnu[PK]f#jK$Form/FormRendererEngineInterface.phpnu[PK]2Form/FormFactoryBuilder.phpnu[PK]E1'")Form/SubmitButtonTypeInterface.phpnu[PK]K'$,Form/FormBuilder.phpnu[PK]YBKForm/ReversedTransformer.phpnu[PK]}p  KPForm/FormError.phpnu[PK]z5 ZForm/ResolvedFormTypeFactory.phpnu[PK]Z)r]Form/FormFactoryInterface.phpnu[PK]X!SnForm/Exception/LogicException.phpnu[PK]yu%|pForm/Exception/ExceptionInterface.phpnu[PK]N#~rForm/Exception/RuntimeException.phpnu[PK]W  (tForm/Exception/AlreadyBoundException.phpnu[PK]K9,wForm/Exception/AlreadySubmittedException.phpnu[PK]1;TT(cyForm/Exception/ErrorMappingException.phpnu[PK]di){Form/Exception/BadMethodCallException.phpnu[PK]_c==*W}Form/Exception/UnexpectedTypeException.phpnu[PK]+RR&Form/Exception/StringCastException.phpnu[PK](dd0Form/Exception/InvalidConfigurationException.phpnu[PK]gBz+ZForm/Exception/InvalidArgumentException.phpnu[PK]SD0Form/Exception/TransformationFailedException.phpnu[PK]é'χForm/Exception/OutOfBoundsException.phpnu[PK]R}jjForm/DataMapperInterface.phpnu[PK]4Nz"z"ƎForm/Button.phpnu[PK]H Form/FormView.phpnu[PK]{d!!#Form/FormConfigBuilderInterface.phpnu[PK]DjNForm/AbstractExtension.phpnu[PK]CForm/ButtonTypeInterface.phpnu[PK]rW W !*Form/DataTransformerInterface.phpnu[PK]>Form/FormRegistryInterface.phpnu[PK]11  Form/Form.phpnu[PK]ObXqq0Form/SubmitButton.phpnu[PK]\g Form/RequestHandlerInterface.phpnu[PK]N̷)ҙForm/ResolvedFormTypeFactoryInterface.phpnu[PK]188AForm/AbstractType.phpnu[PK])..Form/FormRenderer.phpnu[PK]CForm/AbstractTypeExtension.phpnu[PK]"Form/FormEvent.phpnu[PK]-9NNForm/autoloader.phpnu[PK]^}  CssSelector/CssSelector.phpnu[PK]zZ< CssSelector/Parser/Token.phpnu[PK]QQ" CssSelector/Parser/TokenStream.phpnu[PK]6ND1D1CssSelector/Parser/Parser.phpnu[PK];  =3CssSelector/Parser/Reader.phpnu[PK]SkFF*<CssSelector/Parser/Tokenizer/Tokenizer.phpnu[PK]>< 28ECssSelector/Parser/Tokenizer/TokenizerPatterns.phpnu[PK] W552$SCssSelector/Parser/Tokenizer/TokenizerEscaping.phpnu[PK]6\5 5 ,ZCssSelector/Parser/Handler/StringHandler.phpnu[PK]hff/LeCssSelector/Parser/Handler/HandlerInterface.phpnu[PK]0iCssSelector/Parser/Handler/WhitespaceHandler.phpnu[PK]X{*nCssSelector/Parser/Handler/HashHandler.phpnu[PK]8D^^-MuCssSelector/Parser/Handler/CommentHandler.phpnu[PK]e'n,zCssSelector/Parser/Handler/NumberHandler.phpnu[PK]#0)CssSelector/Parser/Handler/IdentifierHandler.phpnu[PK]ҵܗ1CssSelector/Parser/Shortcut/EmptyStringParser.phpnu[PK]TR#[PP+CssSelector/Parser/Shortcut/ClassParser.phpnu[PK]Z>-SCssSelector/Parser/Shortcut/ElementParser.phpnu[PK]5# HH*6CssSelector/Parser/Shortcut/HashParser.phpnu[PK]AEo11&؟CssSelector/Parser/ParserInterface.phpnu[PK]gfGBB,_CssSelector/Exception/ExceptionInterface.phpnu[PK]/pTС2CssSelector/Exception/ExpressionErrorException.phpnu[PK]mc0CssSelector/Exception/InternalErrorException.phpnu[PK]מ.CssSelector/Exception/SyntaxErrorException.phpnu[PK]'[|ɀ(CssSelector/Exception/ParseException.phpnu[PK]pM2!ӶCssSelector/Node/AbstractNode.phpnu[PK]#^[CssSelector/Node/HashNode.phpnu[PK]Г^FF CssSelector/Node/ElementNode.phpnu[PK]x {CssSelector/Node/Specificity.phpnu[PK]x!CssSelector/Node/FunctionNode.phpnu[PK],+?)RCssSelector/Node/CombinedSelectorNode.phpnu[PK]!sCssSelector/Node/SelectorNode.phpnu[PK]FK K "XCssSelector/Node/AttributeNode.phpnu[PK] iCssSelector/Node/ClassNode.phpnu[PK]bb!2CssSelector/Node/NegationNode.phpnu[PK].22CssSelector/Node/PseudoNode.phpnu[PK]rI"f CssSelector/Node/NodeInterface.phpnu[PK]uUUP CssSelector/autoloader.phpnu[PK]Ѽ`PP- CssSelector/XPath/Extension/NodeExtension.phpnu[PK] 4$ CssSelector/XPath/Extension/PseudoClassExtension.phpnu[PK]$pBB-4 CssSelector/XPath/Extension/HtmlExtension.phpnu[PK]c-1mO CssSelector/XPath/Extension/AbstractExtension.phpnu[PK]܍:T CssSelector/XPath/Extension/AttributeMatchingExtension.phpnu[PK]u1g CssSelector/XPath/Extension/FunctionExtension.phpnu[PK]||2 CssSelector/XPath/Extension/ExtensionInterface.phpnu[PK]x= = 4ׅ CssSelector/XPath/Extension/CombinationExtension.phpnu[PK]r7 7 x CssSelector/XPath/XPathExpr.phpnu[PK]!!  CssSelector/XPath/Translator.phpnu[PK] )ռ CssSelector/XPath/TranslatorInterface.phpnu[PK]EY HttpFoundation/HeaderBag.phpnu[PK]?` y y : HttpFoundation/Resources/stubs/SessionHandlerInterface.phpnu[PK]ݣ""$ HttpFoundation/ResponseHeaderBag.phpnu[PK]zu00:!HttpFoundation/Session/Storage/PhpBridgeSessionStorage.phpnu[PK]$  9A!HttpFoundation/Session/Storage/MockFileSessionStorage.phpnu[PK]2] 6#!HttpFoundation/Session/Storage/Proxy/AbstractProxy.phpnu[PK]A40!HttpFoundation/Session/Storage/Proxy/NativeProxy.phpnu[PK]mwȡ<4!HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.phpnu[PK]uY0C q=w!HttpFoundation/Session/Storage/Handler/NullSessionHandler.phpnu[PK]k4{ { B|!HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.phpnu[PK]ڏ۹ A׈!HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.phpnu[PK]C&!HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.phpnu[PK]33?!HttpFoundation/Session/Storage/Handler/NativeSessionHandler.phpnu[PK]?yy:'!HttpFoundation/Session/Storage/SessionStorageInterface.phpnu[PK]t337 !HttpFoundation/Session/Storage/NativeSessionStorage.phpnu[PK]g_.!HttpFoundation/Session/Storage/MetadataBag.phpnu[PK]ގ!:!HttpFoundation/Session/Storage/MockArraySessionStorage.phpnu[PK]M&zrr.r"HttpFoundation/Session/SessionBagInterface.phpnu[PK]@WW3B "HttpFoundation/Session/Flash/AutoExpireFlashBag.phpnu[PK]a2"HttpFoundation/Session/Flash/FlashBagInterface.phpnu[PK]W )!"HttpFoundation/Session/Flash/FlashBag.phpnu[PK]:au77"."HttpFoundation/Session/Session.phpnu[PK]0H66;C"HttpFoundation/Session/Attribute/NamespacedAttributeBag.phpnu[PK]e  :@S"HttpFoundation/Session/Attribute/AttributeBagInterface.phpnu[PK]( 1Y"HttpFoundation/Session/Attribute/AttributeBag.phpnu[PK]=\\+e"HttpFoundation/Session/SessionInterface.phpnu[PK]K> x"HttpFoundation/ApacheRequest.phpnu[PK]qugdd{|"HttpFoundation/Request.phpnu[PK]6= )W#HttpFoundation/IpUtils.phpnu[PK]d}޷%%%-e#HttpFoundation/BinaryFileResponse.phpnu[PK]1y*9#HttpFoundation/RequestMatcherInterface.phpnu[PK]Vkb33##HttpFoundation/AcceptHeaderItem.phpnu[PK]nOO+0#HttpFoundation/ExpressionRequestMatcher.phpnu[PK]}xxڧ#HttpFoundation/ServerBag.phpnu[PK]F#HttpFoundation/Cookie.phpnu[PK]ގ##$#HttpFoundation/File/UploadedFile.phpnu[PK]60#HttpFoundation/File/MimeType/MimeTypeGuesser.phpnu[PK] L91#HttpFoundation/File/MimeType/MimeTypeGuesserInterface.phpnu[PK]wnMM9j$HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.phpnu[PK]5p18 $HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.phpnu[PK]q x:$HttpFoundation/File/MimeType/ExtensionGuesserInterface.phpnu[PK]2 k 1$HttpFoundation/File/MimeType/ExtensionGuesser.phpnu[PK]J:$$HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.phpnu[PK]1e7($HttpFoundation/File/Exception/AccessDeniedException.phpnu[PK]gr1F$HttpFoundation/File/Exception/UploadException.phpnu[PK]s-7s$HttpFoundation/File/Exception/FileNotFoundException.phpnu[PK]S==9$HttpFoundation/File/Exception/UnexpectedTypeException.phpnu[PK]o/0$HttpFoundation/File/Exception/FileException.phpnu[PK])`$HttpFoundation/File/File.phpnu[PK]8{?!A$HttpFoundation/RequestMatcher.phpnu[PK]pߋߋk$HttpFoundation/Response.phpnu[PK]\8h%HttpFoundation/ParameterBag.phpnu[PK]s #%HttpFoundation/StreamedResponse.phpnu[PK]a.h%HttpFoundation/AcceptHeader.phpnu[PK]͢|ѣ%HttpFoundation/JsonResponse.phpnu[PK]Pi9%HttpFoundation/FileBag.phpnu[PK]_DK #D%HttpFoundation/RedirectResponse.phpnu[PK]7 E E %HttpFoundation/RequestStack.phpnu[PK]PE XX%HttpFoundation/autoloader.phpnu[PK]!/R%Process/ProcessBuilder.phpnu[PK]nL L  %Process/ProcessUtils.phpnu[PK]@s%Process/PhpProcess.phpnu[PK]!,$  %Process/ExecutableFinder.phpnu[PK]W$u&Process/Exception/LogicException.phpnu[PK]<( &Process/Exception/ExceptionInterface.phpnu[PK]>H& &Process/Exception/RuntimeException.phpnu[PK]2{{. &Process/Exception/ProcessTimedOutException.phpnu[PK]_,&Process/Exception/ProcessFailedException.phpnu[PK]˅.&Process/Exception/InvalidArgumentException.phpnu[PK]g''V&Process/ProcessPipes.phpnu[PK]MD&Process/Process.phpnu[PK]y>8&Process/PhpExecutableFinder.phpnu[PK]0QQ&Process/autoloader.phpnu[PK] `&BrowserKit/Request.phpnu[PK]9;""&BrowserKit/Cookie.phpnu[PK]/  'BrowserKit/History.phpnu[PK]㩑eCCU'BrowserKit/Client.phpnu[PK]l- - ]'BrowserKit/Response.phpnu[PK]*k'BrowserKit/CookieJar.phpnu[PK].TT'BrowserKit/autoloader.phpnu[PK]%'Console/Descriptor/TextDescriptor.phpnu[PK]m !'Console/Descriptor/Descriptor.phpnu[PK]sX -'Console/Descriptor/ApplicationDescription.phpnu[PK]ﶲ%%$'Console/Descriptor/XmlDescriptor.phpnu[PK]lP..)`'Console/Descriptor/MarkdownDescriptor.phpnu[PK]Duu%(Console/Descriptor/JsonDescriptor.phpnu[PK]JZ0<*(Console/Descriptor/DescriptorInterface.phpnu[PK]v$$%(Console/Resources/bin/hiddeninput.exenu[PK]LUҊҊA<(Console/Application.phpnu[PK]2VZ(Console/Shell.phpnu[PK]Z\(Console/Helper/Helper.phpnu[PK]"U1  #(Console/Helper/DescriptorHelper.phpnu[PK] (Console/Helper/HelperSet.phpnu[PK]gse"(Console/Helper/FormatterHelper.phpnu[PK]&>@>@)Console/Helper/DialogHelper.phpnu[PK]22D)Console/Helper/TableHelper.phpnu[PK]s H#w)Console/Helper/InputAwareHelper.phpnu[PK]|po.o.!Cz)Console/Helper/ProgressHelper.phpnu[PK]z")Console/Helper/HelperInterface.phpnu[PK]onj&&*H)Console/Formatter/OutputFormatterStyle.phpnu[PK]v /)Console/Formatter/OutputFormatterStyleStack.phpnu[PK]53 )Console/Formatter/OutputFormatterStyleInterface.phpnu[PK]Jp. )Console/Formatter/OutputFormatterInterface.phpnu[PK]l%N)Console/Formatter/OutputFormatter.phpnu[PK]zM M "h)Console/Output/OutputInterface.phpnu[PK]F$_*Console/Output/NullOutput.phpnu[PK],QM M ( *Console/Output/StreamOutput.phpnu[PK]t|X4hh!*Console/Output/BufferedOutput.phpnu[PK]0KK)}*Console/Output/ConsoleOutputInterface.phpnu[PK]sQ;;!*Console/Output/Output.phpnu[PK]ϱ} } -*Console/Output/ConsoleOutput.phpnu[PK]||-&%r9*Console/Event/ConsoleCommandEvent.phpnu[PK] ;*Console/Event/ConsoleEvent.phpnu[PK]sKAA'A*Console/Event/ConsoleExceptionEvent.phpnu[PK]Z&&'%H*Console/Event/ConsoleTerminateEvent.phpnu[PK]\0EM*Console/ConsoleEvents.phpnu[PK]m_ _ S*Console/Command/HelpCommand.phpnu[PK]Ƙ7@7@^*Console/Command/Command.phpnu[PK] x *Console/Command/ListCommand.phpnu[PK]hrf f $"*Console/Tester/ApplicationTester.phpnu[PK]~H(R ܷ*Console/Tester/CommandTester.phpnu[PK].QQH*Console/autoloader.phpnu[PK]9Kh^^%*Console/Input/InputAwareInterface.phpnu[PK]AM66 *Console/Input/InputInterface.phpnu[PK]1E(0(0!*Console/Input/InputDefinition.phpnu[PK]p%% +Console/Input/ArrayInput.phpnu[PK]Q))#+Console/Input/ArgvInput.phpnu[PK]OVVM+Console/Input/InputOption.phpnu[PK]' d+Console/Input/InputArgument.phpnu[PK]gm(q+Console/Input/Input.phpnu[PK]΂= +Console/Input/StringInput.phpnu[PK]Gk !]+Validator/ConstraintValidator.phpnu[PK]-tZMZM2j+Validator/Resources/translations/validators.ru.xlfnu[PK]b@@2&+Validator/Resources/translations/validators.pt.xlfnu[PK]D#??2',Validator/Resources/translations/validators.en.xlfnu[PK]tý552g,Validator/Resources/translations/validators.he.xlfnu[PK]D#"#"27,Validator/Resources/translations/validators.mn.xlfnu[PK]mwBB2,Validator/Resources/translations/validators.pl.xlfnu[PK]nCC2-Validator/Resources/translations/validators.sl.xlfnu[PK]MM23G-Validator/Resources/translations/validators.el.xlfnu[PK]Y.3552a-Validator/Resources/translations/validators.sq.xlfnu[PK]9>552h-Validator/Resources/translations/validators.da.xlfnu[PK]a222.Validator/Resources/translations/validators.fi.xlfnu[PK]Tл@@54.Validator/Resources/translations/validators.pt_BR.xlfnu[PK]PhBhB2u.Validator/Resources/translations/validators.lt.xlfnu[PK]ժN@@2.Validator/Resources/translations/validators.nl.xlfnu[PK]Q>??2.Validator/Resources/translations/validators.sv.xlfnu[PK](=A=A29/Validator/Resources/translations/validators.gl.xlfnu[PK]v_w,w,2z/Validator/Resources/translations/validators.hy.xlfnu[PK]sE#AA2/Validator/Resources/translations/validators.de.xlfnu[PK]-uCuC2/Validator/Resources/translations/validators.sk.xlfnu[PK] )BB2-0Validator/Resources/translations/validators.cs.xlfnu[PK](ee2p0Validator/Resources/translations/validators.nb.xlfnu[PK]6%=%=50Validator/Resources/translations/validators.zh_CN.xlfnu[PK]wX@X@20Validator/Resources/translations/validators.hr.xlfnu[PK]93XaoAoA21Validator/Resources/translations/validators.hu.xlfnu[PK]1ar==5P1Validator/Resources/translations/validators.zh_TW.xlfnu[PK]@T'%BB21Validator/Resources/translations/validators.vi.xlfnu[PK]e]߭AA751Validator/Resources/translations/validators.sr_Cyrl.xlfnu[PK]AA2I2Validator/Resources/translations/validators.ja.xlfnu[PK]-112T2Validator/Resources/translations/validators.cy.xlfnu[PK]OO22Validator/Resources/translations/validators.ar.xlfnu[PK]qb??22Validator/Resources/translations/validators.lb.xlfnu[PK]"}2A2A2s3Validator/Resources/translations/validators.es.xlfnu[PK]AA2Y3Validator/Resources/translations/validators.ro.xlfnu[PK]τ}K}K2W3Validator/Resources/translations/validators.uk.xlfnu[PK]+ B B263Validator/Resources/translations/validators.fr.xlfnu[PK]=^::2)4Validator/Resources/translations/validators.it.xlfnu[PK] AA2d4Validator/Resources/translations/validators.ca.xlfnu[PK]112l4Validator/Resources/translations/validators.no.xlfnu[PK]L>2Ze5Validator/Resources/translations/validators.id.xlfnu[PK]%N==25Validator/Resources/translations/validators.et.xlfnu[PK] GG25Validator/Resources/translations/validators.fa.xlfnu[PK]@T\442x)6Validator/Resources/translations/validators.af.xlfnu[PK]˺Q1Q12]6Validator/Resources/translations/validators.tr.xlfnu[PK]1^4476Validator/Resources/translations/validators.sr_Latn.xlfnu[PK]\,yzz-6Validator/Constraints/Collection/Required.phpnu[PK]خ zz-6Validator/Constraints/Collection/Optional.phpnu[PK]dXBBb6Validator/Constraints/Issn.phpnu[PK]oo(6Validator/Constraints/RangeValidator.phpnu[PK]S탟6Validator/Constraints/Date.phpnu[PK]cy  "#6Validator/Constraints/DateTime.phpnu[PK]NH"6Validator/Constraints/LessThan.phpnu[PK]mԼ\\16Validator/Constraints/NotIdenticalToValidator.phpnu[PK]('y6Validator/Constraints/TimeValidator.phpnu[PK]I7U6Validator/Constraints/False.phpnu[PK]V`'6Validator/Constraints/IbanValidator.phpnu[PK]BB6Validator/Constraints/Range.phpnu[PK]|4XX&6Validator/Constraints/UrlValidator.phpnu[PK][A)76Validator/Constraints/LessThanOrEqual.phpnu[PK]Hð 7Validator/Constraints/Locale.phpnu[PK]c7Validator/Constraints/Ip.phpnu[PK],,! 7Validator/Constraints/Isbn.phpnu[PK]?57Validator/Constraints/AbstractComparisonValidator.phpnu[PK](.ww57Validator/Constraints/GreaterThanOrEqualValidator.phpnu[PK]> i//#7Validator/Constraints/Existence.phpnu[PK]<8S(> 7Validator/Constraints/ImageValidator.phpnu[PK]D*%77Validator/Constraints/NotNullValidator.phpnu[PK]m\\,W:7Validator/Constraints/AbstractComparison.phpnu[PK]\\+?7Validator/Constraints/LessThanValidator.phpnu[PK]e8B $A7Validator/Constraints/Collection.phpnu[PK]}a%M7Validator/Constraints/GreaterThan.phpnu[PK]~%ɋKO7Validator/Constraints/Valid.phpnu[PK]F'%S7Validator/Constraints/TypeValidator.phpnu[PK]̋ Y7Validator/Constraints/Regex.phpnu[PK]EW^*b7Validator/Constraints/CountryValidator.phpnu[PK] 00;h7Validator/Constraints/Url.phpnu[PK]Q,j7Validator/Constraints/GreaterThanOrEqual.phpnu[PK]zet -m7Validator/Constraints/ExpressionValidator.phpnu[PK]x.`ss"=w7Validator/Constraints/Callback.phpnu[PK]tUה"~7Validator/Constraints/Required.phpnu[PK]rs+"7Validator/Constraints/Optional.phpnu[PK]"-΁7Validator/Constraints/CardSchemeValidator.phpnu[PK] n-7Validator/Constraints/CollectionValidator.phpnu[PK]}&& 7Validator/Constraints/Length.phpnu[PK]7n7Validator/Constraints/Time.phpnu[PK]44'7Validator/Constraints/IssnValidator.phpnu[PK]SnI7Validator/Constraints/Null.phpnu[PK]7Validator/Constraints/All.phpnu[PK]??,4:Validator/Mapping/Loader/LoaderInterface.phpnu[PK];QF11*t7:Validator/Mapping/Loader/XmlFileLoader.phpnu[PK](N:Validator/Mapping/Loader/LoaderChain.phpnu[PK]Tb/'V:Validator/Mapping/Loader/StaticMethodLoader.phpnu[PK]?,_\:Validator/Mapping/Loader/YamlFilesLoader.phpnu[PK] lw#Q Q -D_:Validator/Mapping/Loader/AnnotationLoader.phpnu[PK]t././#k:Validator/Mapping/ClassMetadata.phpnu[PK]$s:Validator/Mapping/Cache/ApcCache.phpnu[PK]+d%%*R:Validator/Mapping/Cache/CacheInterface.phpnu[PK]|$Ѥ:Validator/Mapping/GetterMetadata.phpnu[PK]L8 ( :Validator/ValidationVisitorInterface.phpnu[PK] Sb'b'?:Validator/ValidatorBuilder.phpnu[PK]C0C0':Validator/ExecutionContextInterface.phpnu[PK]d;Validator/Validator.phpnu[PK]oSS+;Validator/autoloader.phpnu[PK]@V.-;Validator/ConstraintViolationListInterface.phpnu[PK]Nm15;EventDispatcher/ContainerAwareEventDispatcher.phpnu[PK]bk 8P;EventDispatcher/Event.phpnu[PK]s ,];EventDispatcher/ImmutableEventDispatcher.phpnu[PK]cG11,f;EventDispatcher/EventSubscriberInterface.phpnu[PK]Y"#l;EventDispatcher/EventDispatcher.phpnu[PK]U ,;EventDispatcher/EventDispatcherInterface.phpnu[PK],DD ӎ;EventDispatcher/GenericEvent.phpnu[PK] ;g;EventDispatcher/Debug/TraceableEventDispatcherInterface.phpnu[PK] YY;EventDispatcher/autoloader.phpnu[PK]:;DomCrawler/Link.phpnu[PK]<4{bb;DomCrawler/Crawler.phpnu[PK]V>"x<Routing/RouteCompilerInterface.phpnu[PK]^==<Routing/Route.phpnu[PK] ff3Y'=Routing/Matcher/RedirectableUrlMatcherInterface.phpnu[PK]''"+=Routing/Matcher/TraceableUrlMatcher.phpnu[PK]`u+==Routing/Matcher/RequestMatcherInterface.phpnu[PK][zdd* C=Routing/Matcher/RedirectableUrlMatcher.phpnu[PK]YIWW&J=Routing/Matcher/Dumper/DumperRoute.phpnu[PK]x}44+wO=Routing/Matcher/Dumper/PhpMatcherDumper.phpnu[PK]?|{(Ӄ=Routing/Matcher/Dumper/MatcherDumper.phpnu[PK]( 1ˇ=Routing/Matcher/Dumper/MatcherDumperInterface.phpnu[PK]N 1=Routing/Matcher/Dumper/DumperPrefixCollection.phpnu[PK]`+=Routing/Matcher/Dumper/DumperCollection.phpnu[PK] bz#z#.=Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu[PK]q q $]=Routing/Matcher/ApacheUrlMatcher.phpnu[PK]GjC"""=Routing/Matcher/UrlMatcher.phpnu[PK] ڗ'=Routing/Matcher/UrlMatcherInterface.phpnu[PK]h=Routing/RequestContext.phpnu[PK]pBQ Q !M>Routing/Loader/YamlFileLoader.phpnu[PK]?-[ -3>Routing/Loader/schema/routing/routing-1.0.xsdnu[PK]nhh =>Routing/Loader/ClosureLoader.phpnu[PK]? ,B>Routing/Loader/AnnotationDirectoryLoader.phpnu[PK]~LW(L>Routing/Loader/AnnotationClassLoader.phpnu[PK]أ2D$D$ j>Routing/Loader/XmlFileLoader.phpnu[PK]Pi{ >Routing/Loader/PhpFileLoader.phpnu[PK]~ޟ '>Routing/Loader/AnnotationFileLoader.phpnu[PK]V˽ >Routing/Annotation/Route.phpnu[PK])(>Routing/Exception/ExceptionInterface.phpnu[PK]j`j/>Routing/Exception/InvalidParameterException.phpnu[PK]njW,>Routing/Exception/RouteNotFoundException.phpnu[PK]==9_>Routing/Exception/MissingMandatoryParametersException.phpnu[PK]JJ/>Routing/Exception/MethodNotAllowedException.phpnu[PK]?]///>Routing/Exception/ResourceNotFoundException.phpnu[PK]U8<>Routing/RouterInterface.phpnu[PK]r( >Routing/RequestContextAwareInterface.phpnu[PK]45>Routing/Generator/Dumper/GeneratorDumperInterface.phpnu[PK]u ',O>Routing/Generator/Dumper/GeneratorDumper.phpnu[PK]1O /Q>Routing/Generator/Dumper/PhpGeneratorDumper.phpnu[PK] 11"l>Routing/Generator/UrlGenerator.phpnu[PK]մ7?Routing/Generator/ConfigurableRequirementsInterface.phpnu[PK]@@+?Routing/Generator/UrlGeneratorInterface.phpnu[PK] %%x(?Routing/Router.phpnu[PK]UcQQN?Routing/autoloader.phpnu[PK]|,{ȪLP?Routing/RouteCollection.phpnu[PK]&%L L "Am?Security/Csrf/CsrfTokenManager.phpnu[PK]VǴ+w?Security/Csrf/CsrfTokenManagerInterface.phpnu[PK] 8?Security/Csrf/TokenStorage/NativeSessionTokenStorage.phpnu[PK]4-?Security/Csrf/TokenStorage/TokenStorageInterface.phpnu[PK]]N N 2?Security/Csrf/TokenStorage/SessionTokenStorage.phpnu[PK]eI2Λ?Security/Csrf/Exception/TokenNotFoundException.phpnu[PK] =6 ?Security/Csrf/TokenGenerator/UriSafeTokenGenerator.phpnu[PK]J,p8?Security/Csrf/TokenGenerator/TokenGeneratorInterface.phpnu[PK]O?Security/Csrf/CsrfToken.phpnu[PK]"C?Security/Http/FirewallMap.phpnu[PK]:&GG@ص?Security/Http/Session/SessionAuthenticationStrategyInterface.phpnu[PK]La[[7?Security/Http/Session/SessionAuthenticationStrategy.phpnu[PK]\\&Q?Security/Http/FirewallMapInterface.phpnu[PK] 6'6'9?Security/Http/Firewall/AbstractAuthenticationListener.phpnu[PK]"?*4?Security/Http/Firewall/ContextListener.phpnu[PK]Z;6@Security/Http/Firewall/AbstractPreAuthenticatedListener.phpnu[PK]&! 6N@Security/Http/Firewall/BasicAuthenticationListener.phpnu[PK]B b  -5%@Security/Http/Firewall/SwitchUserListener.phpnu[PK];@@Security/Http/Firewall/SimpleFormAuthenticationListener.phpnu[PK](T b!b!,X@Security/Http/Firewall/ExceptionListener.phpnu[PK]̗Ez@Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.phpnu[PK]n:@Security/Http/Firewall/SimplePreAuthenticationListener.phpnu[PK]|L@**)u@Security/Http/Firewall/LogoutListener.phpnu[PK]׿ͼ 7@Security/Http/Firewall/DigestAuthenticationListener.phpnu[PK]~k*2@Security/Http/Firewall/ChannelListener.phpnu[PK],}@Security/Http/Firewall/ListenerInterface.phpnu[PK]+/Z Z )@Security/Http/Firewall/AccessListener.phpnu[PK]׺=59@Security/Http/Firewall/X509AuthenticationListener.phpnu[PK]nz+S -y@Security/Http/Firewall/RememberMeListener.phpnu[PK]lٯ:@Security/Http/Firewall/AnonymousAuthenticationListener.phpnu[PK]^V<ASecurity/Http/Authorization/AccessDeniedHandlerInterface.phpnu[PK]a$9 ASecurity/Http/RememberMe/TokenBasedRememberMeServices.phpnu[PK]*b&&7ASecurity/Http/RememberMe/AbstractRememberMeServices.phpnu[PK]Pڕ-LEASecurity/Http/RememberMe/ResponseListener.phpnu[PK]s44CJASecurity/Http/RememberMe/PersistentTokenBasedRememberMeServices.phpnu[PK] z 8'_ASecurity/Http/RememberMe/RememberMeServicesInterface.phpnu[PK]2jJkASecurity/Http/AccessMap.phpnu[PK]`CqASecurity/Http/HttpUtils.phpnu[PK]/ sG ASecurity/Http/SecurityEvents.phpnu[PK]D'ASecurity/Http/Event/SwitchUserEvent.phpnu[PK]Zv}-?ASecurity/Http/Event/InteractiveLoginEvent.phpnu[PK]H]  FASecurity/Http/Authentication/AuthenticationFailureHandlerInterface.phpnu[PK]AH\ݞ<ASecurity/Http/Authentication/SimpleAuthenticationHandler.phpnu[PK]NAFASecurity/Http/Authentication/AuthenticationSuccessHandlerInterface.phpnu[PK] DASecurity/Http/Authentication/DefaultAuthenticationFailureHandler.phpnu[PK]xGA A D;ASecurity/Http/Authentication/DefaultAuthenticationSuccessHandler.phpnu[PK]6O/ASecurity/Http/Logout/LogoutHandlerInterface.phpnu[PK]\ü-LASecurity/Http/Logout/SessionLogoutHandler.phpnu[PK]dd4mASecurity/Http/Logout/CookieClearingLogoutHandler.phpnu[PK]a7ll45ASecurity/Http/Logout/DefaultLogoutSuccessHandler.phpnu[PK]1d6ASecurity/Http/Logout/LogoutSuccessHandlerInterface.phpnu[PK]/``$PASecurity/Http/AccessMapInterface.phpnu[PK]DXV V ASecurity/Http/Firewall.phpnu[PK]י9ASecurity/Http/EntryPoint/FormAuthenticationEntryPoint.phpnu[PK]tZ)K K ;ASecurity/Http/EntryPoint/DigestAuthenticationEntryPoint.phpnu[PK]:BSecurity/Http/EntryPoint/RetryAuthenticationEntryPoint.phpnu[PK]<ݐpp: BSecurity/Http/EntryPoint/BasicAuthenticationEntryPoint.phpnu[PK])'_++>BSecurity/Http/EntryPoint/AuthenticationEntryPointInterface.phpnu[PK]/IBSecurity/Resources/translations/security.vi.xlfnu[PK]U/%BSecurity/Resources/translations/security.el.xlfnu[PK]5˙/5BSecurity/Resources/translations/security.ua.xlfnu[PK]O /EBSecurity/Resources/translations/security.it.xlfnu[PK]) /SBSecurity/Resources/translations/security.ro.xlfnu[PK]m|JJ4aBSecurity/Resources/translations/security.sr_Cyrl.xlfnu[PK]YWg g 4gqBSecurity/Resources/translations/security.sr_Latn.xlfnu[PK]|H /2BSecurity/Resources/translations/security.hu.xlfnu[PK]ţ /?BSecurity/Resources/translations/security.ca.xlfnu[PK]y /ABSecurity/Resources/translations/security.gl.xlfnu[PK] /?BSecurity/Resources/translations/security.lb.xlfnu[PK]o'N /rBSecurity/Resources/translations/security.de.xlfnu[PK].X: : /BSecurity/Resources/translations/security.en.xlfnu[PK](SS/2BSecurity/Resources/translations/security.bg.xlfnu[PK]f488/BSecurity/Resources/translations/security.ja.xlfnu[PK] /{BSecurity/Resources/translations/security.no.xlfnu[PK]M-@/_BSecurity/Resources/translations/security.fa.xlfnu[PK]J J /CSecurity/Resources/translations/security.da.xlfnu[PK]]W W /CSecurity/Resources/translations/security.hr.xlfnu[PK]&MЎ /6*CSecurity/Resources/translations/security.es.xlfnu[PK]Y 2X8CSecurity/Resources/translations/security.pt_BR.xlfnu[PK] ( /BFCSecurity/Resources/translations/security.cs.xlfnu[PK]Dt 2,TCSecurity/Resources/translations/security.zh_CN.xlfnu[PK]w=/aCSecurity/Resources/translations/security.ru.xlfnu[PK]Tkf/qCSecurity/Resources/translations/security.ar.xlfnu[PK]RwD D /CSecurity/Resources/translations/security.id.xlfnu[PK]'{ { /bCSecurity/Resources/translations/security.tr.xlfnu[PK]de /ݼHSecurity/Core/Authorization/AccessDecisionManagerInterface.phpnu[PK]>4eHSecurity/Core/Authorization/Voter/VoterInterface.phpnu[PK]`c 5{HSecurity/Core/Authorization/Voter/ExpressionVoter.phpnu[PK]З~/HSecurity/Core/Authorization/Voter/RoleVoter.phpnu[PK]X,m  8HSecurity/Core/Authorization/Voter/AuthenticatedVoter.phpnu[PK]~f8lHSecurity/Core/Authorization/Voter/RoleHierarchyVoter.phpnu[PK]m25HSecurity/Core/Authorization/AccessDecisionManager.phpnu[PK]D$.." ISecurity/Core/User/UserChecker.phpnu[PK]1G G ISecurity/Core/User/User.phpnu[PK]+,ISecurity/Core/User/UserCheckerInterface.phpnu[PK]/!  + ISecurity/Core/User/InMemoryUserProvider.phpnu[PK]svW W ,{*ISecurity/Core/User/UserProviderInterface.phpnu[PK]6bY Y ,.4ISecurity/Core/User/AdvancedUserInterface.phpnu[PK] $?ISecurity/Core/User/UserInterface.phpnu[PK]^ (IISecurity/Core/User/ChainUserProvider.phpnu[PK]//)ZTISecurity/Core/User/EquatableInterface.phpnu[PK] ,XISecurity/Core/Util/SecureRandomInterface.phpnu[PK]T,,![ISecurity/Core/Util/ClassUtils.phpnu[PK]Ua"FaISecurity/Core/Util/StringUtils.phpnu[PK]Õ  #xhISecurity/Core/Util/SecureRandom.phpnu[PK]l&uISecurity/Core/AuthenticationEvents.phpnu[PK]Eh2;zISecurity/Core/Event/AuthenticationFailureEvent.phpnu[PK]+\ //+O~ISecurity/Core/Event/AuthenticationEvent.phpnu[PK]bM<<4فISecurity/Core/Exception/UnsupportedUserException.phpnu[PK]#q44?yISecurity/Core/Exception/InsufficientAuthenticationException.phpnu[PK]A.ISecurity/Core/Exception/ExceptionInterface.phpnu[PK] ,4ISecurity/Core/Exception/RuntimeException.phpnu[PK]O5zISecurity/Core/Exception/InvalidCsrfTokenException.phpnu[PK]:AA2jISecurity/Core/Exception/AccountStatusException.phpnu[PK]qUSą1 ISecurity/Core/Exception/AccessDeniedException.phpnu[PK]Xss+ISecurity/Core/Exception/LogoutException.phpnu[PK]e1ISecurity/Core/Exception/NonceExpiredException.phpnu[PK]D92ݝISecurity/Core/Exception/TokenNotFoundException.phpnu[PK]z&7РISecurity/Core/Exception/CredentialsExpiredException.phpnu[PK]zz+ISecurity/Core/Exception/LockedException.phpnu[PK]Ε3ISecurity/Core/Exception/BadCredentialsException.phpnu[PK]7w-:ISecurity/Core/Exception/AuthenticationServiceException.phpnu[PK]'3ISecurity/Core/Exception/AuthenticationException.phpnu[PK]@ 5ISecurity/Core/Exception/ProviderNotFoundException.phpnu[PK]և-ISecurity/Core/Exception/DisabledException.phpnu[PK]xB3ɺISecurity/Core/Exception/AccountExpiredException.phpnu[PK]hc0ISecurity/Core/Exception/CookieTheftException.phpnu[PK]ĸFISecurity/Core/Exception/AuthenticationCredentialsNotFoundException.phpnu[PK]ʝ94zISecurity/Core/Exception/InvalidArgumentException.phpnu[PK] 04}}5ISecurity/Core/Exception/UsernameNotFoundException.phpnu[PK]5]7ISecurity/Core/Exception/SessionUnavailableException.phpnu[PK]ZvmAISecurity/Core/Authentication/RememberMe/InMemoryTokenProvider.phpnu[PK]QZZDISecurity/Core/Authentication/RememberMe/PersistentTokenInterface.phpnu[PK] TO;ISecurity/Core/Authentication/RememberMe/PersistentToken.phpnu[PK] CfBISecurity/Core/Authentication/RememberMe/TokenProviderInterface.phpnu[PK]JAJISecurity/Core/Authentication/Provider/RememberMeAuthenticationProvider.phpnu[PK]a""IISecurity/Core/Authentication/Provider/AuthenticationProviderInterface.phpnu[PK]CISecurity/Core/Authentication/Provider/DaoAuthenticationProvider.phpnu[PK]XI'JSecurity/Core/Authentication/Provider/AnonymousAuthenticationProvider.phpnu[PK]>,vvFSJSecurity/Core/Authentication/Provider/SimpleAuthenticationProvider.phpnu[PK]un\ P?JSecurity/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.phpnu[PK]byyD JSecurity/Core/Authentication/Provider/UserAuthenticationProvider.phpnu[PK]r3WWE5JSecurity/Core/Authentication/AuthenticationTrustResolverInterface.phpnu[PK]¬> ##@m;JSecurity/Core/Authentication/SimplePreAuthenticatorInterface.phpnu[PK]W=>JSecurity/Core/Authentication/SimpleAuthenticatorInterface.phpnu[PK]f ?:JSecurity/Core/Authentication/AuthenticationProviderManager.phpnu[PK]J-W;::A JSecurity/Core/Authentication/SimpleFormAuthenticatorInterface.phpnu[PK]:6<JSecurity/Core/Authentication/AuthenticationTrustResolver.phpnu[PK] 77=JSecurity/Core/Validator/Constraints/UserPasswordValidator.phpnu[PK]i4TJSecurity/Core/Validator/Constraints/UserPassword.phpnu[PK]'za! ! !LJSecurity/Core/SecurityContext.phpnu[PK]!@  /JSecurity/Core/Encoder/Pbkdf2PasswordEncoder.phpnu[PK]Æ /JSecurity/Core/Encoder/BCryptPasswordEncoder.phpnu[PK]^6JSecurity/Core/Encoder/MessageDigestPasswordEncoder.phpnu[PK];D(JSecurity/Core/Encoder/EncoderFactory.phpnu[PK]#MMqq1JSecurity/Core/Encoder/EncoderFactoryInterface.phpnu[PK],>"2JSecurity/Core/Encoder/PlaintextPasswordEncoder.phpnu[PK]7 -$JSecurity/Core/Encoder/BasePasswordEncoder.phpnu[PK]E 2iJSecurity/Core/Encoder/PasswordEncoderInterface.phpnu[PK]W"RRKSecurity/autoloader.phpnu[PK]g@Mb b zKFinder/Glob.phpnu[PK]59KFinder/SplFileInfo.phpnu[PK]P  &iKFinder/Comparator/NumberComparator.phpnu[PK]|Fz   #KFinder/Comparator/Comparator.phpnu[PK] $8,KFinder/Comparator/DateComparator.phpnu[PK]7'F2KFinder/Exception/ExceptionInterface.phpnu[PK]cWޫ*4KFinder/Exception/AccessDeniedException.phpnu[PK]P26KFinder/Exception/OperationNotPermitedException.phpnu[PK]9918KFinder/Exception/ShellCommandFailureException.phpnu[PK]>@,/=KFinder/Exception/AdapterFailureException.phpnu[PK]E BKFinder/Expression/Glob.phpnu[PK](^PKFinder/Expression/Regex.phpnu[PK]"HH$iKFinder/Expression/ValueInterface.phpnu[PK] & & KnKFinder/Expression/Expression.phpnu[PK]4˵xKFinder/Shell/Shell.phpnu[PK]5KKFinder/Shell/Command.phpnu[PK]9!2{ { lKFinder/Adapter/PhpAdapter.phpnu[PK] "4KFinder/Adapter/AbstractAdapter.phpnu[PK]}] !KFinder/Adapter/GnuFindAdapter.phpnu[PK]QJ))&KFinder/Adapter/AbstractFindAdapter.phpnu[PK]kA !KFinder/Adapter/BsdFindAdapter.phpnu[PK] #KFinder/Adapter/AdapterInterface.phpnu[PK]dVVLFinder/Finder.phpnu[PK]d2[LFinder/Iterator/ExcludeDirectoryFilterIterator.phpnu[PK]xP+aLFinder/Iterator/SizeRangeFilterIterator.phpnu[PK]n bb*gLFinder/Iterator/FileTypeFilterIterator.phpnu[PK]6s .lLFinder/Iterator/RecursiveDirectoryIterator.phpnu[PK]z"(yLFinder/Iterator/CustomFilterIterator.phpnu[PK] U+uLFinder/Iterator/DateRangeFilterIterator.phpnu[PK]j $LFinder/Iterator/SortableIterator.phpnu[PK] .ʏLFinder/Iterator/MultiplePcreFilterIterator.phpnu[PK]{^ǽ*LFinder/Iterator/FilenameFilterIterator.phpnu[PK],G"-LFinder/Iterator/FilterIterator.phpnu[PK])&LFinder/Iterator/PathFilterIterator.phpnu[PK]ɔ %LFinder/Iterator/FilePathsIterator.phpnu[PK]ʽ-LFinder/Iterator/FilecontentFilterIterator.phpnu[PK]ils_,LFinder/Iterator/DepthRangeFilterIterator.phpnu[PK]%uMPPKLFinder/autoloader.phpnu[PK__}=L